rob_impl.hh revision 1689
111988Sandreas.sandberg@arm.com/*
211988Sandreas.sandberg@arm.com * Copyright (c) 2004-2005 The Regents of The University of Michigan
311988Sandreas.sandberg@arm.com * All rights reserved.
411988Sandreas.sandberg@arm.com *
511988Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without
611988Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are
711988Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright
811988Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer;
911988Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright
1011988Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the
1111988Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution;
1211988Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its
1311988Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from
1411988Sandreas.sandberg@arm.com * this software without specific prior written permission.
1511988Sandreas.sandberg@arm.com *
1611988Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1711988Sandreas.sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1811988Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1911988Sandreas.sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2011988Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2111988Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2211988Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2311988Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2411988Sandreas.sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2511988Sandreas.sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2611988Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2711988Sandreas.sandberg@arm.com */
2811988Sandreas.sandberg@arm.com
2911988Sandreas.sandberg@arm.com#ifndef __CPU_BETA_CPU_ROB_IMPL_HH__
3011988Sandreas.sandberg@arm.com#define __CPU_BETA_CPU_ROB_IMPL_HH__
3111988Sandreas.sandberg@arm.com
3211988Sandreas.sandberg@arm.com#include "cpu/beta_cpu/rob.hh"
3311988Sandreas.sandberg@arm.com
3411988Sandreas.sandberg@arm.comtemplate <class Impl>
3511988Sandreas.sandberg@arm.comROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth)
3611988Sandreas.sandberg@arm.com    : numEntries(_numEntries),
3711988Sandreas.sandberg@arm.com      squashWidth(_squashWidth),
3811988Sandreas.sandberg@arm.com      numInstsInROB(0),
3911988Sandreas.sandberg@arm.com      squashedSeqNum(0)
4011988Sandreas.sandberg@arm.com{
4111988Sandreas.sandberg@arm.com    doneSquashing = true;
4211988Sandreas.sandberg@arm.com}
4311988Sandreas.sandberg@arm.com
4411988Sandreas.sandberg@arm.comtemplate <class Impl>
4511988Sandreas.sandberg@arm.comvoid
4611988Sandreas.sandberg@arm.comROB<Impl>::setCPU(FullCPU *cpu_ptr)
4711988Sandreas.sandberg@arm.com{
4811988Sandreas.sandberg@arm.com    cpu = cpu_ptr;
4912035Sandreas.sandberg@arm.com
5012035Sandreas.sandberg@arm.com    // Set the tail to the beginning of the CPU instruction list so that
5111988Sandreas.sandberg@arm.com    // upon the first instruction being inserted into the ROB, the tail
5211988Sandreas.sandberg@arm.com    // iterator can simply be incremented.
5311988Sandreas.sandberg@arm.com    tail = cpu->instList.begin();
5411988Sandreas.sandberg@arm.com
5512334Sgabeblack@google.com    // Set the squash iterator to the end of the instruction list.
5611988Sandreas.sandberg@arm.com    squashIt = cpu->instList.end();
5711988Sandreas.sandberg@arm.com}
5811988Sandreas.sandberg@arm.com
5911988Sandreas.sandberg@arm.comtemplate <class Impl>
6011988Sandreas.sandberg@arm.comint
6111988Sandreas.sandberg@arm.comROB<Impl>::countInsts()
6211988Sandreas.sandberg@arm.com{
6311988Sandreas.sandberg@arm.com    // Start at 1; if the tail matches cpu->instList.begin(), then there is
6411988Sandreas.sandberg@arm.com    // one inst in the ROB.
6511988Sandreas.sandberg@arm.com    int return_val = 1;
6611988Sandreas.sandberg@arm.com
6711988Sandreas.sandberg@arm.com    // There are quite a few special cases.  Do not use this function other
6811988Sandreas.sandberg@arm.com    // than for debugging purposes.
6911988Sandreas.sandberg@arm.com    if (cpu->instList.begin() == cpu->instList.end()) {
7011988Sandreas.sandberg@arm.com        // In this case there are no instructions in the list.  The ROB
7111988Sandreas.sandberg@arm.com        // must be empty.
7211988Sandreas.sandberg@arm.com        return 0;
7311988Sandreas.sandberg@arm.com    } else if (tail == cpu->instList.end()) {
7411988Sandreas.sandberg@arm.com        // In this case, the tail is not yet pointing to anything valid.
7511988Sandreas.sandberg@arm.com        // The ROB must be empty.
7611988Sandreas.sandberg@arm.com        return 0;
7711988Sandreas.sandberg@arm.com    }
7811988Sandreas.sandberg@arm.com
7911988Sandreas.sandberg@arm.com    // Iterate through the ROB from the head to the tail, counting the
8011988Sandreas.sandberg@arm.com    // entries.
8111988Sandreas.sandberg@arm.com    for (InstIt_t i = cpu->instList.begin(); i != tail; ++i)
8211988Sandreas.sandberg@arm.com    {
8311988Sandreas.sandberg@arm.com        assert(i != cpu->instList.end());
8411988Sandreas.sandberg@arm.com        ++return_val;
8511988Sandreas.sandberg@arm.com    }
8611988Sandreas.sandberg@arm.com
8711988Sandreas.sandberg@arm.com    return return_val;
8811988Sandreas.sandberg@arm.com
8911988Sandreas.sandberg@arm.com    // Because the head won't be tracked properly until the ROB gets the
9011988Sandreas.sandberg@arm.com    // first instruction, and any time that the ROB is empty and has not
9111988Sandreas.sandberg@arm.com    // yet gotten the instruction, this function doesn't work.
9211988Sandreas.sandberg@arm.com//    return numInstsInROB;
9311988Sandreas.sandberg@arm.com}
9411988Sandreas.sandberg@arm.com
9511988Sandreas.sandberg@arm.comtemplate <class Impl>
9611988Sandreas.sandberg@arm.comvoid
9711988Sandreas.sandberg@arm.comROB<Impl>::insertInst(DynInstPtr &inst)
9811988Sandreas.sandberg@arm.com{
9911988Sandreas.sandberg@arm.com    // Make sure we have the right number of instructions.
10011988Sandreas.sandberg@arm.com    assert(numInstsInROB == countInsts());
10111988Sandreas.sandberg@arm.com    // Make sure the instruction is valid.
10211988Sandreas.sandberg@arm.com    assert(inst);
10311988Sandreas.sandberg@arm.com
10411988Sandreas.sandberg@arm.com    DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC());
10511988Sandreas.sandberg@arm.com
10611988Sandreas.sandberg@arm.com    // If the ROB is full then exit.
10711988Sandreas.sandberg@arm.com    assert(numInstsInROB != numEntries);
10811988Sandreas.sandberg@arm.com
10911988Sandreas.sandberg@arm.com    ++numInstsInROB;
11011988Sandreas.sandberg@arm.com
11111988Sandreas.sandberg@arm.com    // Increment the tail iterator, moving it one instruction back.
11211988Sandreas.sandberg@arm.com    // There is a special case if the ROB was empty prior to this insertion,
11311988Sandreas.sandberg@arm.com    // in which case the tail will be pointing at instList.end().  If that
11411988Sandreas.sandberg@arm.com    // happens, then reset the tail to the beginning of the list.
11511988Sandreas.sandberg@arm.com    if (tail != cpu->instList.end()) {
11611988Sandreas.sandberg@arm.com        ++tail;
11711988Sandreas.sandberg@arm.com    } else {
11811988Sandreas.sandberg@arm.com        tail = cpu->instList.begin();
11911988Sandreas.sandberg@arm.com    }
12011988Sandreas.sandberg@arm.com
12111988Sandreas.sandberg@arm.com    // Make sure the tail iterator is actually pointing at the instruction
12211988Sandreas.sandberg@arm.com    // added.
12311988Sandreas.sandberg@arm.com    assert((*tail) == inst);
12411988Sandreas.sandberg@arm.com
12511988Sandreas.sandberg@arm.com    DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB);
12611988Sandreas.sandberg@arm.com
12711988Sandreas.sandberg@arm.com}
12811988Sandreas.sandberg@arm.com
12911988Sandreas.sandberg@arm.com// Whatever calls this function needs to ensure that it properly frees up
13011988Sandreas.sandberg@arm.com// registers prior to this function.
13111988Sandreas.sandberg@arm.comtemplate <class Impl>
13211988Sandreas.sandberg@arm.comvoid
13311988Sandreas.sandberg@arm.comROB<Impl>::retireHead()
13411988Sandreas.sandberg@arm.com{
13512036Sandreas.sandberg@arm.com    assert(numInstsInROB == countInsts());
13612036Sandreas.sandberg@arm.com    assert(numInstsInROB > 0);
13711988Sandreas.sandberg@arm.com
13811988Sandreas.sandberg@arm.com    // Get the head ROB instruction.
13911988Sandreas.sandberg@arm.com    DynInstPtr head_inst = cpu->instList.front();
14011988Sandreas.sandberg@arm.com
14111988Sandreas.sandberg@arm.com    // Make certain this can retire.
14211988Sandreas.sandberg@arm.com    assert(head_inst->readyToCommit());
14311988Sandreas.sandberg@arm.com
14411988Sandreas.sandberg@arm.com    DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, "
14511988Sandreas.sandberg@arm.com            "instruction PC %#x, seq num %i\n", head_inst->readPC(),
14611988Sandreas.sandberg@arm.com            head_inst->seqNum);
14711988Sandreas.sandberg@arm.com
14811988Sandreas.sandberg@arm.com    // Keep track of how many instructions are in the ROB.
14911988Sandreas.sandberg@arm.com    --numInstsInROB;
15011988Sandreas.sandberg@arm.com
15111988Sandreas.sandberg@arm.com    // Tell CPU to remove the instruction from the list of instructions.
15211988Sandreas.sandberg@arm.com    // A special case is needed if the instruction being retired is the
15311988Sandreas.sandberg@arm.com    // only instruction in the ROB; otherwise the tail iterator will become
15411988Sandreas.sandberg@arm.com    // invalidated.
15511988Sandreas.sandberg@arm.com    cpu->removeFrontInst(head_inst);
15611988Sandreas.sandberg@arm.com
15711988Sandreas.sandberg@arm.com    if (numInstsInROB == 0) {
15811988Sandreas.sandberg@arm.com        tail = cpu->instList.end();
15911988Sandreas.sandberg@arm.com    }
16011988Sandreas.sandberg@arm.com}
16111988Sandreas.sandberg@arm.com
16211988Sandreas.sandberg@arm.comtemplate <class Impl>
16311988Sandreas.sandberg@arm.combool
16411988Sandreas.sandberg@arm.comROB<Impl>::isHeadReady()
16511988Sandreas.sandberg@arm.com{
16611988Sandreas.sandberg@arm.com    if (numInstsInROB != 0) {
16711988Sandreas.sandberg@arm.com        return cpu->instList.front()->readyToCommit();
16811988Sandreas.sandberg@arm.com    }
16912036Sandreas.sandberg@arm.com
17012035Sandreas.sandberg@arm.com    return false;
17112035Sandreas.sandberg@arm.com}
17212035Sandreas.sandberg@arm.com
17311988Sandreas.sandberg@arm.comtemplate <class Impl>
17411988Sandreas.sandberg@arm.comunsigned
17511988Sandreas.sandberg@arm.comROB<Impl>::numFreeEntries()
17611988Sandreas.sandberg@arm.com{
17711988Sandreas.sandberg@arm.com    assert(numInstsInROB == countInsts());
17811988Sandreas.sandberg@arm.com
17911988Sandreas.sandberg@arm.com    return numEntries - numInstsInROB;
18011988Sandreas.sandberg@arm.com}
18111988Sandreas.sandberg@arm.com
18211988Sandreas.sandberg@arm.comtemplate <class Impl>
18311988Sandreas.sandberg@arm.comvoid
18411988Sandreas.sandberg@arm.comROB<Impl>::doSquash()
18511988Sandreas.sandberg@arm.com{
18611988Sandreas.sandberg@arm.com    DPRINTF(ROB, "ROB: Squashing instructions.\n");
18711988Sandreas.sandberg@arm.com
18811988Sandreas.sandberg@arm.com    assert(squashIt != cpu->instList.end());
18911988Sandreas.sandberg@arm.com
19011988Sandreas.sandberg@arm.com    for (int numSquashed = 0;
19111988Sandreas.sandberg@arm.com         numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum;
19211988Sandreas.sandberg@arm.com         ++numSquashed)
19311988Sandreas.sandberg@arm.com    {
19411988Sandreas.sandberg@arm.com        // Ensure that the instruction is younger.
19511988Sandreas.sandberg@arm.com        assert((*squashIt)->seqNum > squashedSeqNum);
19611988Sandreas.sandberg@arm.com
19711988Sandreas.sandberg@arm.com        DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n",
19811988Sandreas.sandberg@arm.com                (*squashIt)->readPC(), (*squashIt)->seqNum);
19911988Sandreas.sandberg@arm.com
20011988Sandreas.sandberg@arm.com        // Mark the instruction as squashed, and ready to commit so that
20111988Sandreas.sandberg@arm.com        // it can drain out of the pipeline.
20211988Sandreas.sandberg@arm.com        (*squashIt)->setSquashed();
20311988Sandreas.sandberg@arm.com
20411988Sandreas.sandberg@arm.com        (*squashIt)->setCanCommit();
20511988Sandreas.sandberg@arm.com
20611988Sandreas.sandberg@arm.com        // Special case for when squashing due to a syscall.  It's possible
20711988Sandreas.sandberg@arm.com        // that the squash happened after the head instruction was already
20811988Sandreas.sandberg@arm.com        // committed, meaning that (*squashIt)->seqNum != squashedSeqNum
20911988Sandreas.sandberg@arm.com        // will never be false.  Normally the squash would never be able
21011988Sandreas.sandberg@arm.com        // to go past the head of the ROB; in this case it might, so it
21111988Sandreas.sandberg@arm.com        // must be handled otherwise it will segfault.
21211988Sandreas.sandberg@arm.com#ifndef FULL_SYSTEM
21311988Sandreas.sandberg@arm.com        if (squashIt == cpu->instList.begin()) {
21411988Sandreas.sandberg@arm.com            DPRINTF(ROB, "ROB: Reached head of instruction list while "
21511988Sandreas.sandberg@arm.com                    "squashing.\n");
21611988Sandreas.sandberg@arm.com
21711988Sandreas.sandberg@arm.com            squashIt = cpu->instList.end();
21811988Sandreas.sandberg@arm.com
21911988Sandreas.sandberg@arm.com            doneSquashing = true;
22011988Sandreas.sandberg@arm.com
22111988Sandreas.sandberg@arm.com            return;
22211988Sandreas.sandberg@arm.com        }
22311988Sandreas.sandberg@arm.com#endif
22411988Sandreas.sandberg@arm.com
22511988Sandreas.sandberg@arm.com        // Move the tail iterator to the next instruction.
22611988Sandreas.sandberg@arm.com        squashIt--;
22711988Sandreas.sandberg@arm.com    }
22811988Sandreas.sandberg@arm.com
22911988Sandreas.sandberg@arm.com
23011988Sandreas.sandberg@arm.com    // Check if ROB is done squashing.
23111988Sandreas.sandberg@arm.com    if ((*squashIt)->seqNum == squashedSeqNum) {
23211988Sandreas.sandberg@arm.com        DPRINTF(ROB, "ROB: Done squashing instructions.\n");
23311988Sandreas.sandberg@arm.com
23411988Sandreas.sandberg@arm.com        squashIt = cpu->instList.end();
23511988Sandreas.sandberg@arm.com
23611988Sandreas.sandberg@arm.com        doneSquashing = true;
23711988Sandreas.sandberg@arm.com    }
23811988Sandreas.sandberg@arm.com}
23911988Sandreas.sandberg@arm.com
24011988Sandreas.sandberg@arm.comtemplate <class Impl>
24111988Sandreas.sandberg@arm.comvoid
24211988Sandreas.sandberg@arm.comROB<Impl>::squash(InstSeqNum squash_num)
24311988Sandreas.sandberg@arm.com{
24412011Sgabeblack@google.com    DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n");
24511988Sandreas.sandberg@arm.com    doneSquashing = false;
24611988Sandreas.sandberg@arm.com
24711988Sandreas.sandberg@arm.com    squashedSeqNum = squash_num;
24811988Sandreas.sandberg@arm.com
24911988Sandreas.sandberg@arm.com    assert(tail != cpu->instList.end());
25011988Sandreas.sandberg@arm.com
25111988Sandreas.sandberg@arm.com    squashIt = tail;
25211988Sandreas.sandberg@arm.com
25311988Sandreas.sandberg@arm.com    doSquash();
25411988Sandreas.sandberg@arm.com}
25511988Sandreas.sandberg@arm.com
25611988Sandreas.sandberg@arm.comtemplate <class Impl>
25711988Sandreas.sandberg@arm.comuint64_t
25811988Sandreas.sandberg@arm.comROB<Impl>::readHeadPC()
25911988Sandreas.sandberg@arm.com{
26011988Sandreas.sandberg@arm.com    assert(numInstsInROB == countInsts());
26111988Sandreas.sandberg@arm.com
26211988Sandreas.sandberg@arm.com    DynInstPtr head_inst = cpu->instList.front();
26311988Sandreas.sandberg@arm.com
26411988Sandreas.sandberg@arm.com    return head_inst->readPC();
26511988Sandreas.sandberg@arm.com}
26611988Sandreas.sandberg@arm.com
26711988Sandreas.sandberg@arm.comtemplate <class Impl>
26811988Sandreas.sandberg@arm.comuint64_t
26911988Sandreas.sandberg@arm.comROB<Impl>::readHeadNextPC()
27011988Sandreas.sandberg@arm.com{
27111988Sandreas.sandberg@arm.com    assert(numInstsInROB == countInsts());
27211988Sandreas.sandberg@arm.com
27311988Sandreas.sandberg@arm.com    DynInstPtr head_inst = cpu->instList.front();
27411988Sandreas.sandberg@arm.com
27511988Sandreas.sandberg@arm.com    return head_inst->readNextPC();
27611988Sandreas.sandberg@arm.com}
27711988Sandreas.sandberg@arm.com
27811988Sandreas.sandberg@arm.comtemplate <class Impl>
27911988Sandreas.sandberg@arm.comInstSeqNum
28011988Sandreas.sandberg@arm.comROB<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