rob_impl.hh revision 1717
12SN/A/*
211071SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan
311071SN/A * All rights reserved.
411071SN/A *
511071SN/A * Redistribution and use in source and binary forms, with or without
611071SN/A * modification, are permitted provided that the following conditions are
711071SN/A * met: redistributions of source code must retain the above copyright
811071SN/A * notice, this list of conditions and the following disclaimer;
911071SN/A * redistributions in binary form must reproduce the above copyright
1011071SN/A * notice, this list of conditions and the following disclaimer in the
1111071SN/A * documentation and/or other materials provided with the distribution;
1211071SN/A * neither the name of the copyright holders nor the names of its
1311071SN/A * contributors may be used to endorse or promote products derived from
141762SN/A * this software without specific prior written permission.
152SN/A *
162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272SN/A */
282SN/A
292SN/A#ifndef __CPU_BETA_CPU_ROB_IMPL_HH__
302SN/A#define __CPU_BETA_CPU_ROB_IMPL_HH__
312SN/A
322SN/A#include "cpu/o3/rob.hh"
332SN/A
342SN/Atemplate <class Impl>
352SN/AROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth)
362SN/A    : numEntries(_numEntries),
372SN/A      squashWidth(_squashWidth),
382SN/A      numInstsInROB(0),
392665SN/A      squashedSeqNum(0)
402665SN/A{
412665SN/A    doneSquashing = true;
422SN/A}
432SN/A
442SN/Atemplate <class Impl>
452SN/Avoid
462SN/AROB<Impl>::setCPU(FullCPU *cpu_ptr)
472SN/A{
4811263Sandreas.sandberg@arm.com    cpu = cpu_ptr;
4911263Sandreas.sandberg@arm.com
50146SN/A    // Set the tail to the beginning of the CPU instruction list so that
512SN/A    // upon the first instruction being inserted into the ROB, the tail
522SN/A    // iterator can simply be incremented.
532SN/A    tail = cpu->instList.begin();
542SN/A
551954SN/A    // Set the squash iterator to the end of the instruction list.
56146SN/A    squashIt = cpu->instList.end();
578232SN/A}
588232SN/A
5911263Sandreas.sandberg@arm.comtemplate <class Impl>
6011263Sandreas.sandberg@arm.comint
6111263Sandreas.sandberg@arm.comROB<Impl>::countInsts()
624762SN/A{
638229SN/A    // Start at 1; if the tail matches cpu->instList.begin(), then there is
641078SN/A    // one inst in the ROB.
651078SN/A    int return_val = 1;
662SN/A
672SN/A    // There are quite a few special cases.  Do not use this function other
682SN/A    // than for debugging purposes.
694981SN/A    if (cpu->instList.begin() == cpu->instList.end()) {
704981SN/A        // In this case there are no instructions in the list.  The ROB
712SN/A        // must be empty.
725034SN/A        return 0;
735034SN/A    } else if (tail == cpu->instList.end()) {
745034SN/A        // In this case, the tail is not yet pointing to anything valid.
755034SN/A        // The ROB must be empty.
762SN/A        return 0;
774981SN/A    }
784981SN/A
794981SN/A    // Iterate through the ROB from the head to the tail, counting the
802SN/A    // entries.
812SN/A    for (InstIt_t i = cpu->instList.begin(); i != tail; ++i)
822SN/A    {
832SN/A        assert(i != cpu->instList.end());
841435SN/A        ++return_val;
851435SN/A    }
862SN/A
871435SN/A    return return_val;
881435SN/A
892SN/A    // Because the head won't be tracked properly until the ROB gets the
902SN/A    // first instruction, and any time that the ROB is empty and has not
914981SN/A    // yet gotten the instruction, this function doesn't work.
924981SN/A//    return numInstsInROB;
934981SN/A}
944981SN/A
954981SN/Atemplate <class Impl>
964981SN/Avoid
974981SN/AROB<Impl>::insertInst(DynInstPtr &inst)
984981SN/A{
994981SN/A    // Make sure we have the right number of instructions.
1004981SN/A    assert(numInstsInROB == countInsts());
1014981SN/A    // Make sure the instruction is valid.
1024981SN/A    assert(inst);
1034981SN/A
1044981SN/A    DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC());
1054981SN/A
1064981SN/A    // If the ROB is full then exit.
1074981SN/A    assert(numInstsInROB != numEntries);
108633SN/A
1092SN/A    ++numInstsInROB;
1102SN/A
1112SN/A    // Increment the tail iterator, moving it one instruction back.
1122SN/A    // There is a special case if the ROB was empty prior to this insertion,
1132SN/A    // in which case the tail will be pointing at instList.end().  If that
1142SN/A    // happens, then reset the tail to the beginning of the list.
1151435SN/A    if (tail != cpu->instList.end()) {
1161954SN/A        ++tail;
1171435SN/A    } else {
1181954SN/A        tail = cpu->instList.begin();
11911071SN/A    }
1201435SN/A
1212SN/A    // Make sure the tail iterator is actually pointing at the instruction
1222SN/A    // added.
12310905SN/A    assert((*tail) == inst);
124558SN/A
12510905SN/A    DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB);
12610905SN/A
127558SN/A}
128558SN/A
129558SN/A// Whatever calls this function needs to ensure that it properly frees up
13010905SN/A// registers prior to this function.
131558SN/Atemplate <class Impl>
13210905SN/Avoid
13310905SN/AROB<Impl>::retireHead()
134558SN/A{
135558SN/A    assert(numInstsInROB == countInsts());
136558SN/A    assert(numInstsInROB > 0);
1372566SN/A
138633SN/A    // Get the head ROB instruction.
139633SN/A    DynInstPtr head_inst = cpu->instList.front();
140633SN/A
141633SN/A    // Make certain this can retire.
142633SN/A    assert(head_inst->readyToCommit());
143633SN/A
144633SN/A    DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, "
1452SN/A            "instruction PC %#x, seq num %i\n", head_inst->readPC(),
1462SN/A            head_inst->seqNum);
1472SN/A
1482SN/A    // Keep track of how many instructions are in the ROB.
1492SN/A    --numInstsInROB;
150633SN/A
151633SN/A    // Tell CPU to remove the instruction from the list of instructions.
15211071SN/A    // A special case is needed if the instruction being retired is the
15311071SN/A    // only instruction in the ROB; otherwise the tail iterator will become
15411071SN/A    // invalidated.
155633SN/A    cpu->removeFrontInst(head_inst);
15611071SN/A
157633SN/A    if (numInstsInROB == 0) {
158633SN/A        tail = cpu->instList.end();
159195SN/A    }
1602SN/A}
1612SN/A
1622SN/Atemplate <class Impl>
1632SN/Abool
1642SN/AROB<Impl>::isHeadReady()
1652SN/A{
16611071SN/A    if (numInstsInROB != 0) {
16711071SN/A        return cpu->instList.front()->readyToCommit();
16811071SN/A    }
16911071SN/A
17011071SN/A    return false;
17111071SN/A}
17211071SN/A
17311071SN/Atemplate <class Impl>
17411071SN/Aunsigned
17511071SN/AROB<Impl>::numFreeEntries()
17611071SN/A{
17711071SN/A    assert(numInstsInROB == countInsts());
17811071SN/A
17911071SN/A    return numEntries - numInstsInROB;
18011071SN/A}
18111071SN/A
18211071SN/Atemplate <class Impl>
1832SN/Avoid
1842566SN/AROB<Impl>::doSquash()
1852SN/A{
1862SN/A    DPRINTF(ROB, "ROB: Squashing instructions.\n");
187633SN/A
1882SN/A    assert(squashIt != cpu->instList.end());
1892SN/A
1902SN/A    for (int numSquashed = 0;
191633SN/A         numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum;
1922SN/A         ++numSquashed)
1932SN/A    {
1942SN/A        // Ensure that the instruction is younger.
1951961SN/A        assert((*squashIt)->seqNum > squashedSeqNum);
1965190SN/A
1975190SN/A        DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n",
1985190SN/A                (*squashIt)->readPC(), (*squashIt)->seqNum);
199633SN/A
200633SN/A        // Mark the instruction as squashed, and ready to commit so that
2017823SN/A        // it can drain out of the pipeline.
2022SN/A        (*squashIt)->setSquashed();
2032SN/A
2042SN/A        (*squashIt)->setCanCommit();
2052SN/A
206558SN/A        // Special case for when squashing due to a syscall.  It's possible
20710905SN/A        // that the squash happened after the head instruction was already
208558SN/A        // committed, meaning that (*squashIt)->seqNum != squashedSeqNum
20910469SN/A        // will never be false.  Normally the squash would never be able
21010905SN/A        // to go past the head of the ROB; in this case it might, so it
2111435SN/A        // must be handled otherwise it will segfault.
21210905SN/A#ifndef FULL_SYSTEM
213558SN/A        if (squashIt == cpu->instList.begin()) {
214633SN/A            DPRINTF(ROB, "ROB: Reached head of instruction list while "
21510905SN/A                    "squashing.\n");
216558SN/A
217633SN/A            squashIt = cpu->instList.end();
21810905SN/A
219574SN/A            doneSquashing = true;
220574SN/A
22111071SN/A            return;
22211071SN/A        }
22311071SN/A#endif
22411071SN/A
22511071SN/A        // Move the tail iterator to the next instruction.
22611071SN/A        squashIt--;
22711071SN/A    }
22811071SN/A
22911071SN/A
230558SN/A    // Check if ROB is done squashing.
231558SN/A    if ((*squashIt)->seqNum == squashedSeqNum) {
232558SN/A        DPRINTF(ROB, "ROB: Done squashing instructions.\n");
23310905SN/A
234558SN/A        squashIt = cpu->instList.end();
235574SN/A
23610905SN/A        doneSquashing = true;
237574SN/A    }
23810469SN/A}
23910905SN/A
240558SN/Atemplate <class Impl>
241558SN/Avoid
242574SN/AROB<Impl>::squash(InstSeqNum squash_num)
24310905SN/A{
244558SN/A    DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n");
245574SN/A    doneSquashing = false;
24610905SN/A
2475606SN/A    squashedSeqNum = squash_num;
248558SN/A
24911071SN/A    assert(tail != cpu->instList.end());
25011071SN/A
25111071SN/A    squashIt = tail;
25211071SN/A
25311071SN/A    doSquash();
25411071SN/A}
25511071SN/A
25611071SN/Atemplate <class Impl>
25711071SN/Auint64_t
25811071SN/AROB<Impl>::readHeadPC()
25911071SN/A{
26011071SN/A    assert(numInstsInROB == countInsts());
26111071SN/A
26211071SN/A    DynInstPtr head_inst = cpu->instList.front();
26311071SN/A
26411071SN/A    return head_inst->readPC();
26511071SN/A}
26611071SN/A
26711071SN/Atemplate <class Impl>
26811071SN/Auint64_t
26911071SN/AROB<Impl>::readHeadNextPC()
27011071SN/A{
27111071SN/A    assert(numInstsInROB == countInsts());
27211071SN/A
27311071SN/A    DynInstPtr head_inst = cpu->instList.front();
274558SN/A
275558SN/A    return head_inst->readNextPC();
2764762SN/A}
2774762SN/A
2782SN/Atemplate <class Impl>
2794981SN/AInstSeqNum
2802SN/AROB<Impl>::readHeadSeqNum()
281{
282    // Return the last sequence number that has not been squashed.  Other
283    // stages can use it to squash any instructions younger than the current
284    // tail.
285    DynInstPtr head_inst = cpu->instList.front();
286
287    return head_inst->seqNum;
288}
289
290template <class Impl>
291uint64_t
292ROB<Impl>::readTailPC()
293{
294    assert(numInstsInROB == countInsts());
295
296    assert(tail != cpu->instList.end());
297
298    return (*tail)->readPC();
299}
300
301template <class Impl>
302InstSeqNum
303ROB<Impl>::readTailSeqNum()
304{
305    // Return the last sequence number that has not been squashed.  Other
306    // stages can use it to squash any instructions younger than the current
307    // tail.
308    return (*tail)->seqNum;
309}
310
311#endif // __CPU_BETA_CPU_ROB_IMPL_HH__
312