rob_impl.hh revision 1689
11689SN/A/*
22329SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan
31689SN/A * All rights reserved.
41689SN/A *
51689SN/A * Redistribution and use in source and binary forms, with or without
61689SN/A * modification, are permitted provided that the following conditions are
71689SN/A * met: redistributions of source code must retain the above copyright
81689SN/A * notice, this list of conditions and the following disclaimer;
91689SN/A * redistributions in binary form must reproduce the above copyright
101689SN/A * notice, this list of conditions and the following disclaimer in the
111689SN/A * documentation and/or other materials provided with the distribution;
121689SN/A * neither the name of the copyright holders nor the names of its
131689SN/A * contributors may be used to endorse or promote products derived from
141689SN/A * this software without specific prior written permission.
151689SN/A *
161689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu */
282665Ssaidi@eecs.umich.edu
292831Sksewell@umich.edu#ifndef __CPU_BETA_CPU_ROB_IMPL_HH__
301689SN/A#define __CPU_BETA_CPU_ROB_IMPL_HH__
311689SN/A
321858SN/A#include "cpu/beta_cpu/rob.hh"
331717SN/A
341060SN/Atemplate <class Impl>
352292SN/AROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth)
362292SN/A    : numEntries(_numEntries),
371061SN/A      squashWidth(_squashWidth),
382292SN/A      numInstsInROB(0),
392292SN/A      squashedSeqNum(0)
402292SN/A{
411060SN/A    doneSquashing = true;
421060SN/A}
431060SN/A
442292SN/Atemplate <class Impl>
451060SN/Avoid
462292SN/AROB<Impl>::setCPU(FullCPU *cpu_ptr)
472877Sksewell@umich.edu{
482292SN/A    cpu = cpu_ptr;
492292SN/A
502292SN/A    // Set the tail to the beginning of the CPU instruction list so that
512292SN/A    // upon the first instruction being inserted into the ROB, the tail
522292SN/A    // iterator can simply be incremented.
532292SN/A    tail = cpu->instList.begin();
542292SN/A
552292SN/A    // Set the squash iterator to the end of the instruction list.
562292SN/A    squashIt = cpu->instList.end();
572292SN/A}
582292SN/A
592292SN/Atemplate <class Impl>
602292SN/Aint
612292SN/AROB<Impl>::countInsts()
622292SN/A{
632292SN/A    // Start at 1; if the tail matches cpu->instList.begin(), then there is
642292SN/A    // one inst in the ROB.
652292SN/A    int return_val = 1;
662292SN/A
672292SN/A    // There are quite a few special cases.  Do not use this function other
682292SN/A    // than for debugging purposes.
692292SN/A    if (cpu->instList.begin() == cpu->instList.end()) {
702292SN/A        // In this case there are no instructions in the list.  The ROB
712292SN/A        // must be empty.
722292SN/A        return 0;
732292SN/A    } else if (tail == cpu->instList.end()) {
742292SN/A        // In this case, the tail is not yet pointing to anything valid.
752292SN/A        // The ROB must be empty.
762292SN/A        return 0;
772292SN/A    }
782292SN/A
792292SN/A    // Iterate through the ROB from the head to the tail, counting the
802292SN/A    // entries.
812292SN/A    for (InstIt_t i = cpu->instList.begin(); i != tail; ++i)
822292SN/A    {
832292SN/A        assert(i != cpu->instList.end());
842292SN/A        ++return_val;
852292SN/A    }
862292SN/A
872292SN/A    return return_val;
882292SN/A
892292SN/A    // Because the head won't be tracked properly until the ROB gets the
902292SN/A    // first instruction, and any time that the ROB is empty and has not
912292SN/A    // yet gotten the instruction, this function doesn't work.
922292SN/A//    return numInstsInROB;
932292SN/A}
942292SN/A
952292SN/Atemplate <class Impl>
962292SN/Avoid
972292SN/AROB<Impl>::insertInst(DynInstPtr &inst)
982292SN/A{
992292SN/A    // Make sure we have the right number of instructions.
1001060SN/A    assert(numInstsInROB == countInsts());
1011060SN/A    // Make sure the instruction is valid.
1021061SN/A    assert(inst);
1031060SN/A
1042733Sktlim@umich.edu    DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC());
1051060SN/A
1061060SN/A    // If the ROB is full then exit.
1071060SN/A    assert(numInstsInROB != numEntries);
1082292SN/A
1092292SN/A    ++numInstsInROB;
1102292SN/A
1112292SN/A    // Increment the tail iterator, moving it one instruction back.
1121060SN/A    // There is a special case if the ROB was empty prior to this insertion,
1132292SN/A    // in which case the tail will be pointing at instList.end().  If that
1142292SN/A    // happens, then reset the tail to the beginning of the list.
1152292SN/A    if (tail != cpu->instList.end()) {
1162292SN/A        ++tail;
1172292SN/A    } else {
1182292SN/A        tail = cpu->instList.begin();
1192292SN/A    }
1202292SN/A
1212292SN/A    // Make sure the tail iterator is actually pointing at the instruction
1222292SN/A    // added.
1232292SN/A    assert((*tail) == inst);
1242292SN/A
1252292SN/A    DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB);
1262292SN/A
1272307SN/A}
1282307SN/A
1292307SN/A// Whatever calls this function needs to ensure that it properly frees up
1302307SN/A// registers prior to this function.
1312307SN/Atemplate <class Impl>
1322307SN/Avoid
1332307SN/AROB<Impl>::retireHead()
1342307SN/A{
1352307SN/A    assert(numInstsInROB == countInsts());
1362307SN/A    assert(numInstsInROB > 0);
1372307SN/A
1382307SN/A    // Get the head ROB instruction.
1392307SN/A    DynInstPtr head_inst = cpu->instList.front();
1402307SN/A
1412307SN/A    // Make certain this can retire.
1422307SN/A    assert(head_inst->readyToCommit());
1432307SN/A
1442307SN/A    DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, "
1452307SN/A            "instruction PC %#x, seq num %i\n", head_inst->readPC(),
1462307SN/A            head_inst->seqNum);
1472307SN/A
1482307SN/A    // Keep track of how many instructions are in the ROB.
1492307SN/A    --numInstsInROB;
1502307SN/A
1512307SN/A    // Tell CPU to remove the instruction from the list of instructions.
1522292SN/A    // A special case is needed if the instruction being retired is the
1532292SN/A    // only instruction in the ROB; otherwise the tail iterator will become
1542292SN/A    // invalidated.
1552292SN/A    cpu->removeFrontInst(head_inst);
1562292SN/A
1572292SN/A    if (numInstsInROB == 0) {
1582292SN/A        tail = cpu->instList.end();
1592292SN/A    }
1602292SN/A}
1612292SN/A
1622292SN/Atemplate <class Impl>
1632292SN/Abool
1642292SN/AROB<Impl>::isHeadReady()
1652292SN/A{
1662292SN/A    if (numInstsInROB != 0) {
1672292SN/A        return cpu->instList.front()->readyToCommit();
1682292SN/A    }
1692292SN/A
1702292SN/A    return false;
1712292SN/A}
1722292SN/A
1732292SN/Atemplate <class Impl>
1742292SN/Aunsigned
1752292SN/AROB<Impl>::numFreeEntries()
1762292SN/A{
1772292SN/A    assert(numInstsInROB == countInsts());
1782292SN/A
1792292SN/A    return numEntries - numInstsInROB;
1802292SN/A}
1812292SN/A
1821060SN/Atemplate <class Impl>
1831060SN/Avoid
1841061SN/AROB<Impl>::doSquash()
1851060SN/A{
1861060SN/A    DPRINTF(ROB, "ROB: Squashing instructions.\n");
1871060SN/A
1882292SN/A    assert(squashIt != cpu->instList.end());
1891061SN/A
1902292SN/A    for (int numSquashed = 0;
1912292SN/A         numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum;
1921060SN/A         ++numSquashed)
1932292SN/A    {
1942292SN/A        // Ensure that the instruction is younger.
1951060SN/A        assert((*squashIt)->seqNum > squashedSeqNum);
1962292SN/A
1972292SN/A        DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n",
1982292SN/A                (*squashIt)->readPC(), (*squashIt)->seqNum);
1992292SN/A
2002292SN/A        // Mark the instruction as squashed, and ready to commit so that
2011060SN/A        // it can drain out of the pipeline.
2021060SN/A        (*squashIt)->setSquashed();
2031061SN/A
2041060SN/A        (*squashIt)->setCanCommit();
2051061SN/A
2061060SN/A        // Special case for when squashing due to a syscall.  It's possible
2072292SN/A        // that the squash happened after the head instruction was already
2081060SN/A        // committed, meaning that (*squashIt)->seqNum != squashedSeqNum
2091060SN/A        // will never be false.  Normally the squash would never be able
2102292SN/A        // to go past the head of the ROB; in this case it might, so it
2111060SN/A        // must be handled otherwise it will segfault.
2121060SN/A#ifndef FULL_SYSTEM
2131060SN/A        if (squashIt == cpu->instList.begin()) {
2142292SN/A            DPRINTF(ROB, "ROB: Reached head of instruction list while "
2151060SN/A                    "squashing.\n");
2162292SN/A
2172292SN/A            squashIt = cpu->instList.end();
2182292SN/A
2192292SN/A            doneSquashing = true;
2202292SN/A
2212292SN/A            return;
2221060SN/A        }
2231060SN/A#endif
2242292SN/A
2252292SN/A        // Move the tail iterator to the next instruction.
2262292SN/A        squashIt--;
2272292SN/A    }
2282292SN/A
2292292SN/A
2302292SN/A    // Check if ROB is done squashing.
2312292SN/A    if ((*squashIt)->seqNum == squashedSeqNum) {
2322292SN/A        DPRINTF(ROB, "ROB: Done squashing instructions.\n");
2332292SN/A
2341060SN/A        squashIt = cpu->instList.end();
2351060SN/A
2362292SN/A        doneSquashing = true;
2371060SN/A    }
2381060SN/A}
2391060SN/A
2401060SN/Atemplate <class Impl>
2412329SN/Avoid
2421061SN/AROB<Impl>::squash(InstSeqNum squash_num)
2431060SN/A{
2441060SN/A    DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n");
2451060SN/A    doneSquashing = false;
2462292SN/A
2472292SN/A    squashedSeqNum = squash_num;
2482292SN/A
2492292SN/A    assert(tail != cpu->instList.end());
2502292SN/A
2512292SN/A    squashIt = tail;
2522292SN/A
2532292SN/A    doSquash();
2542292SN/A}
2552292SN/A
2562292SN/Atemplate <class Impl>
2572329SN/Auint64_t
2582292SN/AROB<Impl>::readHeadPC()
2592292SN/A{
2602292SN/A    assert(numInstsInROB == countInsts());
2612292SN/A
2622292SN/A    DynInstPtr head_inst = cpu->instList.front();
2632292SN/A
2641061SN/A    return head_inst->readPC();
2651060SN/A}
2661060SN/A
2672292SN/Atemplate <class Impl>
2681060SN/Auint64_t
2692292SN/AROB<Impl>::readHeadNextPC()
2701858SN/A{
2711060SN/A    assert(numInstsInROB == countInsts());
2721060SN/A
2732292SN/A    DynInstPtr head_inst = cpu->instList.front();
2742292SN/A
2751060SN/A    return head_inst->readNextPC();
2761060SN/A}
2771060SN/A
2782292SN/Atemplate <class Impl>
2791060SN/AInstSeqNum
2802731Sktlim@umich.eduROB<Impl>::readHeadSeqNum()
2812292SN/A{
2822292SN/A    // Return the last sequence number that has not been squashed.  Other
2832292SN/A    // stages can use it to squash any instructions younger than the current
2842292SN/A    // tail.
2852292SN/A    DynInstPtr head_inst = cpu->instList.front();
2862292SN/A
2872292SN/A    return head_inst->seqNum;
2882329SN/A}
2892329SN/A
2902329SN/Atemplate <class Impl>
2911681SN/Auint64_t
2921060SN/AROB<Impl>::readTailPC()
2932329SN/A{
2941061SN/A    assert(numInstsInROB == countInsts());
2951060SN/A
2961060SN/A    assert(tail != cpu->instList.end());
2971060SN/A
2981060SN/A    return (*tail)->readPC();
2992292SN/A}
3002292SN/A
3012292SN/Atemplate <class Impl>
3022292SN/AInstSeqNum
3032292SN/AROB<Impl>::readTailSeqNum()
3042329SN/A{
3052292SN/A    // Return the last sequence number that has not been squashed.  Other
3062292SN/A    // stages can use it to squash any instructions younger than the current
3072292SN/A    // tail.
3082292SN/A    return (*tail)->seqNum;
3092292SN/A}
3102292SN/A
3112292SN/A#endif // __CPU_BETA_CPU_ROB_IMPL_HH__
3122292SN/A