rob_impl.hh revision 2665
11689SN/A/*
21689SN/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 * Authors: Kevin Lim
291689SN/A */
301689SN/A
311755SN/A#ifndef __CPU_O3_CPU_ROB_IMPL_HH__
321755SN/A#define __CPU_O3_CPU_ROB_IMPL_HH__
331060SN/A
341858SN/A#include "config/full_system.hh"
351717SN/A#include "cpu/o3/rob.hh"
361060SN/A
371061SN/Atemplate <class Impl>
381060SN/AROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth)
391060SN/A    : numEntries(_numEntries),
401060SN/A      squashWidth(_squashWidth),
411060SN/A      numInstsInROB(0),
421060SN/A      squashedSeqNum(0)
431060SN/A{
441060SN/A    doneSquashing = true;
451060SN/A}
461060SN/A
471061SN/Atemplate <class Impl>
481060SN/Avoid
491060SN/AROB<Impl>::setCPU(FullCPU *cpu_ptr)
501060SN/A{
511060SN/A    cpu = cpu_ptr;
521060SN/A
531061SN/A    // Set the tail to the beginning of the CPU instruction list so that
541061SN/A    // upon the first instruction being inserted into the ROB, the tail
551061SN/A    // iterator can simply be incremented.
561060SN/A    tail = cpu->instList.begin();
571060SN/A
581061SN/A    // Set the squash iterator to the end of the instruction list.
591060SN/A    squashIt = cpu->instList.end();
601060SN/A}
611060SN/A
621061SN/Atemplate <class Impl>
631060SN/Aint
641060SN/AROB<Impl>::countInsts()
651060SN/A{
661061SN/A    // Start at 1; if the tail matches cpu->instList.begin(), then there is
671061SN/A    // one inst in the ROB.
681061SN/A    int return_val = 1;
691061SN/A
701061SN/A    // There are quite a few special cases.  Do not use this function other
711061SN/A    // than for debugging purposes.
721061SN/A    if (cpu->instList.begin() == cpu->instList.end()) {
731061SN/A        // In this case there are no instructions in the list.  The ROB
741061SN/A        // must be empty.
751061SN/A        return 0;
761061SN/A    } else if (tail == cpu->instList.end()) {
771061SN/A        // In this case, the tail is not yet pointing to anything valid.
781061SN/A        // The ROB must be empty.
791061SN/A        return 0;
801061SN/A    }
811060SN/A
821060SN/A    // Iterate through the ROB from the head to the tail, counting the
831060SN/A    // entries.
841061SN/A    for (InstIt_t i = cpu->instList.begin(); i != tail; ++i)
851060SN/A    {
861060SN/A        assert(i != cpu->instList.end());
871061SN/A        ++return_val;
881060SN/A    }
891060SN/A
901060SN/A    return return_val;
911061SN/A
921060SN/A    // Because the head won't be tracked properly until the ROB gets the
931060SN/A    // first instruction, and any time that the ROB is empty and has not
941060SN/A    // yet gotten the instruction, this function doesn't work.
951061SN/A//    return numInstsInROB;
961060SN/A}
971060SN/A
981061SN/Atemplate <class Impl>
991060SN/Avoid
1001061SN/AROB<Impl>::insertInst(DynInstPtr &inst)
1011060SN/A{
1021060SN/A    // Make sure we have the right number of instructions.
1031060SN/A    assert(numInstsInROB == countInsts());
1041060SN/A    // Make sure the instruction is valid.
1051060SN/A    assert(inst);
1061060SN/A
1071060SN/A    DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC());
1081060SN/A
1091060SN/A    // If the ROB is full then exit.
1101060SN/A    assert(numInstsInROB != numEntries);
1111060SN/A
1121060SN/A    ++numInstsInROB;
1131060SN/A
1141060SN/A    // Increment the tail iterator, moving it one instruction back.
1151060SN/A    // There is a special case if the ROB was empty prior to this insertion,
1161060SN/A    // in which case the tail will be pointing at instList.end().  If that
1171060SN/A    // happens, then reset the tail to the beginning of the list.
1181060SN/A    if (tail != cpu->instList.end()) {
1191061SN/A        ++tail;
1201060SN/A    } else {
1211060SN/A        tail = cpu->instList.begin();
1221060SN/A    }
1231060SN/A
1241060SN/A    // Make sure the tail iterator is actually pointing at the instruction
1251060SN/A    // added.
1261060SN/A    assert((*tail) == inst);
1271060SN/A
1281060SN/A    DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB);
1291060SN/A
1301060SN/A}
1311060SN/A
1321060SN/A// Whatever calls this function needs to ensure that it properly frees up
1331060SN/A// registers prior to this function.
1341061SN/Atemplate <class Impl>
1351060SN/Avoid
1361060SN/AROB<Impl>::retireHead()
1371060SN/A{
1381060SN/A    assert(numInstsInROB == countInsts());
1391061SN/A    assert(numInstsInROB > 0);
1401060SN/A
1411060SN/A    // Get the head ROB instruction.
1421681SN/A    DynInstPtr head_inst = cpu->instList.front();
1431060SN/A
1441060SN/A    // Make certain this can retire.
1451060SN/A    assert(head_inst->readyToCommit());
1461060SN/A
1471060SN/A    DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, "
1481060SN/A            "instruction PC %#x, seq num %i\n", head_inst->readPC(),
1491060SN/A            head_inst->seqNum);
1501060SN/A
1511060SN/A    // Keep track of how many instructions are in the ROB.
1521060SN/A    --numInstsInROB;
1531060SN/A
1541060SN/A    // Tell CPU to remove the instruction from the list of instructions.
1551060SN/A    // A special case is needed if the instruction being retired is the
1561060SN/A    // only instruction in the ROB; otherwise the tail iterator will become
1571060SN/A    // invalidated.
1581681SN/A    cpu->removeFrontInst(head_inst);
1591681SN/A
1601681SN/A    if (numInstsInROB == 0) {
1611060SN/A        tail = cpu->instList.end();
1621060SN/A    }
1631060SN/A}
1641060SN/A
1651061SN/Atemplate <class Impl>
1661060SN/Abool
1671060SN/AROB<Impl>::isHeadReady()
1681060SN/A{
1691060SN/A    if (numInstsInROB != 0) {
1701062SN/A        return cpu->instList.front()->readyToCommit();
1711060SN/A    }
1721060SN/A
1731060SN/A    return false;
1741060SN/A}
1751060SN/A
1761061SN/Atemplate <class Impl>
1771060SN/Aunsigned
1781060SN/AROB<Impl>::numFreeEntries()
1791060SN/A{
1801060SN/A    assert(numInstsInROB == countInsts());
1811060SN/A
1821060SN/A    return numEntries - numInstsInROB;
1831060SN/A}
1841060SN/A
1851061SN/Atemplate <class Impl>
1861060SN/Avoid
1871060SN/AROB<Impl>::doSquash()
1881060SN/A{
1891060SN/A    DPRINTF(ROB, "ROB: Squashing instructions.\n");
1901060SN/A
1911060SN/A    assert(squashIt != cpu->instList.end());
1921060SN/A
1931060SN/A    for (int numSquashed = 0;
1941060SN/A         numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum;
1951060SN/A         ++numSquashed)
1961060SN/A    {
1971060SN/A        // Ensure that the instruction is younger.
1981060SN/A        assert((*squashIt)->seqNum > squashedSeqNum);
1991060SN/A
2001060SN/A        DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n",
2011060SN/A                (*squashIt)->readPC(), (*squashIt)->seqNum);
2021060SN/A
2031060SN/A        // Mark the instruction as squashed, and ready to commit so that
2041060SN/A        // it can drain out of the pipeline.
2051060SN/A        (*squashIt)->setSquashed();
2061060SN/A
2071060SN/A        (*squashIt)->setCanCommit();
2081060SN/A
2091061SN/A        // Special case for when squashing due to a syscall.  It's possible
2101061SN/A        // that the squash happened after the head instruction was already
2111061SN/A        // committed, meaning that (*squashIt)->seqNum != squashedSeqNum
2121061SN/A        // will never be false.  Normally the squash would never be able
2131061SN/A        // to go past the head of the ROB; in this case it might, so it
2141061SN/A        // must be handled otherwise it will segfault.
2151858SN/A#if !FULL_SYSTEM
2161060SN/A        if (squashIt == cpu->instList.begin()) {
2171060SN/A            DPRINTF(ROB, "ROB: Reached head of instruction list while "
2181060SN/A                    "squashing.\n");
2191060SN/A
2201060SN/A            squashIt = cpu->instList.end();
2211060SN/A
2221060SN/A            doneSquashing = true;
2231060SN/A
2241060SN/A            return;
2251060SN/A        }
2261060SN/A#endif
2271060SN/A
2281060SN/A        // Move the tail iterator to the next instruction.
2291060SN/A        squashIt--;
2301060SN/A    }
2311060SN/A
2321060SN/A
2331060SN/A    // Check if ROB is done squashing.
2341060SN/A    if ((*squashIt)->seqNum == squashedSeqNum) {
2351060SN/A        DPRINTF(ROB, "ROB: Done squashing instructions.\n");
2361060SN/A
2371060SN/A        squashIt = cpu->instList.end();
2381060SN/A
2391060SN/A        doneSquashing = true;
2401060SN/A    }
2411060SN/A}
2421060SN/A
2431061SN/Atemplate <class Impl>
2441060SN/Avoid
2451060SN/AROB<Impl>::squash(InstSeqNum squash_num)
2461060SN/A{
2471060SN/A    DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n");
2481060SN/A    doneSquashing = false;
2491060SN/A
2501060SN/A    squashedSeqNum = squash_num;
2511060SN/A
2521060SN/A    assert(tail != cpu->instList.end());
2531060SN/A
2541060SN/A    squashIt = tail;
2551060SN/A
2561060SN/A    doSquash();
2571060SN/A}
2581060SN/A
2591061SN/Atemplate <class Impl>
2601060SN/Auint64_t
2611060SN/AROB<Impl>::readHeadPC()
2621060SN/A{
2631060SN/A    assert(numInstsInROB == countInsts());
2641060SN/A
2651061SN/A    DynInstPtr head_inst = cpu->instList.front();
2661060SN/A
2671060SN/A    return head_inst->readPC();
2681060SN/A}
2691060SN/A
2701061SN/Atemplate <class Impl>
2711060SN/Auint64_t
2721060SN/AROB<Impl>::readHeadNextPC()
2731060SN/A{
2741060SN/A    assert(numInstsInROB == countInsts());
2751060SN/A
2761061SN/A    DynInstPtr head_inst = cpu->instList.front();
2771060SN/A
2781060SN/A    return head_inst->readNextPC();
2791060SN/A}
2801060SN/A
2811061SN/Atemplate <class Impl>
2821060SN/AInstSeqNum
2831060SN/AROB<Impl>::readHeadSeqNum()
2841060SN/A{
2851060SN/A    // Return the last sequence number that has not been squashed.  Other
2861060SN/A    // stages can use it to squash any instructions younger than the current
2871060SN/A    // tail.
2881061SN/A    DynInstPtr head_inst = cpu->instList.front();
2891060SN/A
2901060SN/A    return head_inst->seqNum;
2911060SN/A}
2921060SN/A
2931061SN/Atemplate <class Impl>
2941060SN/Auint64_t
2951060SN/AROB<Impl>::readTailPC()
2961060SN/A{
2971060SN/A    assert(numInstsInROB == countInsts());
2981060SN/A
2991060SN/A    assert(tail != cpu->instList.end());
3001060SN/A
3011060SN/A    return (*tail)->readPC();
3021060SN/A}
3031060SN/A
3041061SN/Atemplate <class Impl>
3051060SN/AInstSeqNum
3061060SN/AROB<Impl>::readTailSeqNum()
3071060SN/A{
3081060SN/A    // Return the last sequence number that has not been squashed.  Other
3091060SN/A    // stages can use it to squash any instructions younger than the current
3101060SN/A    // tail.
3111060SN/A    return (*tail)->seqNum;
3121060SN/A}
3131060SN/A
3141755SN/A#endif // __CPU_O3_CPU_ROB_IMPL_HH__
315