rob_impl.hh revision 1061
11689SN/A#ifndef __ROB_IMPL_HH__
27598Sminkyu.jeong@arm.com#define __ROB_IMPL_HH__
37598Sminkyu.jeong@arm.com
47598Sminkyu.jeong@arm.com#include "cpu/beta_cpu/rob.hh"
57598Sminkyu.jeong@arm.com
67598Sminkyu.jeong@arm.comtemplate <class Impl>
77598Sminkyu.jeong@arm.comROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth)
87598Sminkyu.jeong@arm.com    : numEntries(_numEntries),
97598Sminkyu.jeong@arm.com      squashWidth(_squashWidth),
107598Sminkyu.jeong@arm.com      numInstsInROB(0),
117598Sminkyu.jeong@arm.com      squashedSeqNum(0)
127598Sminkyu.jeong@arm.com{
137598Sminkyu.jeong@arm.com    doneSquashing = true;
142326SN/A}
151689SN/A
161689SN/Atemplate <class Impl>
171689SN/Avoid
181689SN/AROB<Impl>::setCPU(FullCPU *cpu_ptr)
191689SN/A{
201689SN/A    cpu = cpu_ptr;
211689SN/A
221689SN/A    // Set the tail to the beginning of the CPU instruction list so that
231689SN/A    // upon the first instruction being inserted into the ROB, the tail
241689SN/A    // iterator can simply be incremented.
251689SN/A    tail = cpu->instList.begin();
261689SN/A
271689SN/A    // Set the squash iterator to the end of the instruction list.
281689SN/A    squashIt = cpu->instList.end();
291689SN/A}
301689SN/A
311689SN/Atemplate <class Impl>
321689SN/Aint
331689SN/AROB<Impl>::countInsts()
341689SN/A{
351689SN/A    // Start at 1; if the tail matches cpu->instList.begin(), then there is
361689SN/A    // one inst in the ROB.
371689SN/A    int return_val = 1;
381689SN/A
392665Ssaidi@eecs.umich.edu    // There are quite a few special cases.  Do not use this function other
402665Ssaidi@eecs.umich.edu    // than for debugging purposes.
411689SN/A    if (cpu->instList.begin() == cpu->instList.end()) {
421689SN/A        // In this case there are no instructions in the list.  The ROB
431060SN/A        // must be empty.
441060SN/A        return 0;
451689SN/A    } else if (tail == cpu->instList.end()) {
461060SN/A        // In this case, the tail is not yet pointing to anything valid.
471060SN/A        // The ROB must be empty.
481060SN/A        return 0;
497813Ssteve.reinhardt@amd.com    }
506658Snate@binkert.org
512292SN/A    // Iterate through the ROB from the head to the tail, counting the
521717SN/A    // entries.
535529Snate@binkert.org    for (InstIt_t i = cpu->instList.begin(); i != tail; ++i)
541060SN/A    {
556221Snate@binkert.org        assert(i != cpu->instList.end());
566221Snate@binkert.org        ++return_val;
571681SN/A    }
585529Snate@binkert.org
592873Sktlim@umich.edu    return return_val;
604329Sktlim@umich.edu
614329Sktlim@umich.edu    // Because the head won't be tracked properly until the ROB gets the
624329Sktlim@umich.edu    // first instruction, and any time that the ROB is empty and has not
632292SN/A    // yet gotten the instruction, this function doesn't work.
642292SN/A//    return numInstsInROB;
652292SN/A}
662292SN/A
672820Sktlim@umich.edutemplate <class Impl>
682292SN/Avoid
692820Sktlim@umich.eduROB<Impl>::insertInst(DynInstPtr &inst)
702820Sktlim@umich.edu{
715529Snate@binkert.org    // Make sure we have the right number of instructions.
722307SN/A    assert(numInstsInROB == countInsts());
731060SN/A    // Make sure the instruction is valid.
742292SN/A    assert(inst);
752292SN/A
762292SN/A    DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC());
771060SN/A
781060SN/A    // If the ROB is full then exit.
791060SN/A    assert(numInstsInROB != numEntries);
801060SN/A
811060SN/A    ++numInstsInROB;
821060SN/A
831681SN/A    // Increment the tail iterator, moving it one instruction back.
846221Snate@binkert.org    // There is a special case if the ROB was empty prior to this insertion,
856221Snate@binkert.org    // in which case the tail will be pointing at instList.end().  If that
866221Snate@binkert.org    // happens, then reset the tail to the beginning of the list.
876221Snate@binkert.org    if (tail != cpu->instList.end()) {
882292SN/A        ++tail;
892292SN/A    } else {
902820Sktlim@umich.edu        tail = cpu->instList.begin();
912820Sktlim@umich.edu    }
922292SN/A
932292SN/A    // Make sure the tail iterator is actually pointing at the instruction
942820Sktlim@umich.edu    // added.
952820Sktlim@umich.edu    assert((*tail) == inst);
962292SN/A
972292SN/A    DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB);
982292SN/A
992292SN/A}
1002292SN/A
1012292SN/A// Whatever calls this function needs to ensure that it properly frees up
1022292SN/A// registers prior to this function.
1032292SN/Atemplate <class Impl>
1041060SN/Avoid
1051060SN/AROB<Impl>::retireHead()
1061681SN/A{
1071062SN/A    assert(numInstsInROB == countInsts());
1082292SN/A    assert(numInstsInROB > 0);
1091062SN/A
1102301SN/A    DynInstPtr head_inst;
1112301SN/A
1121062SN/A    // Get the head ROB instruction.
1132727Sktlim@umich.edu    head_inst = cpu->instList.front();
1141062SN/A
1151062SN/A    // Make certain this can retire.
1161062SN/A    assert(head_inst->readyToCommit());
1171062SN/A
1181062SN/A    DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, "
1191062SN/A            "instruction PC %#x, seq num %i\n", head_inst->readPC(),
1201062SN/A            head_inst->seqNum);
1211062SN/A
1221062SN/A    // Keep track of how many instructions are in the ROB.
1231062SN/A    --numInstsInROB;
1241062SN/A
1251062SN/A    // Tell CPU to remove the instruction from the list of instructions.
1261062SN/A    // A special case is needed if the instruction being retired is the
1271062SN/A    // only instruction in the ROB; otherwise the tail iterator will become
1281062SN/A    // invalidated.
1291062SN/A    if (tail == cpu->instList.begin()) {
1301062SN/A        cpu->removeFrontInst(head_inst);
1311062SN/A        tail = cpu->instList.end();
1321062SN/A    } else {
1331062SN/A        cpu->removeFrontInst(head_inst);
1341062SN/A    }
1351062SN/A}
1361062SN/A
1371062SN/Atemplate <class Impl>
1381062SN/Abool
1391062SN/AROB<Impl>::isHeadReady()
1401062SN/A{
1411062SN/A    if (numInstsInROB != 0) {
1421062SN/A        DynInstPtr head_inst = cpu->instList.front();
1431062SN/A
1441062SN/A        return head_inst->readyToCommit();
1451062SN/A    }
1461062SN/A
1471062SN/A    return false;
1481062SN/A}
1491062SN/A
1501062SN/Atemplate <class Impl>
1511062SN/Aunsigned
1521062SN/AROB<Impl>::numFreeEntries()
1531062SN/A{
1541062SN/A    assert(numInstsInROB == countInsts());
1552292SN/A
1562292SN/A    return numEntries - numInstsInROB;
1572292SN/A}
1582292SN/A
1591062SN/Atemplate <class Impl>
1601062SN/Avoid
1611062SN/AROB<Impl>::doSquash()
1621062SN/A{
1631062SN/A    DPRINTF(ROB, "ROB: Squashing instructions.\n");
1641062SN/A
1651062SN/A    assert(squashIt != cpu->instList.end());
1662292SN/A
1672292SN/A    for (int numSquashed = 0;
1682292SN/A         numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum;
1692292SN/A         ++numSquashed)
1702292SN/A    {
1712292SN/A        // Ensure that the instruction is younger.
1722292SN/A        assert((*squashIt)->seqNum > squashedSeqNum);
1732292SN/A
1742292SN/A        DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n",
1752292SN/A                (*squashIt)->readPC(), (*squashIt)->seqNum);
1762301SN/A
1772727Sktlim@umich.edu        // Mark the instruction as squashed, and ready to commit so that
1782353SN/A        // it can drain out of the pipeline.
1792727Sktlim@umich.edu        (*squashIt)->setSquashed();
1802727Sktlim@umich.edu
1812727Sktlim@umich.edu        (*squashIt)->setCanCommit();
1826221Snate@binkert.org
1832353SN/A        // Special case for when squashing due to a syscall.  It's possible
1842727Sktlim@umich.edu        // that the squash happened after the head instruction was already
1852727Sktlim@umich.edu        // committed, meaning that (*squashIt)->seqNum != squashedSeqNum
1862727Sktlim@umich.edu        // will never be false.  Normally the squash would never be able
1872727Sktlim@umich.edu        // to go past the head of the ROB; in this case it might, so it
1882353SN/A        // must be handled otherwise it will segfault.
1892727Sktlim@umich.edu#ifndef FULL_SYSTEM
1902727Sktlim@umich.edu        if (squashIt == cpu->instList.begin()) {
1912727Sktlim@umich.edu            DPRINTF(ROB, "ROB: Reached head of instruction list while "
1926221Snate@binkert.org                    "squashing.\n");
1932301SN/A
1942301SN/A            squashIt = cpu->instList.end();
1952727Sktlim@umich.edu
1962301SN/A            doneSquashing = true;
1972727Sktlim@umich.edu
1986221Snate@binkert.org            return;
1992301SN/A        }
2002301SN/A#endif
2012727Sktlim@umich.edu
2022301SN/A        // Move the tail iterator to the next instruction.
2032727Sktlim@umich.edu        squashIt--;
2046221Snate@binkert.org    }
2052301SN/A
2062301SN/A
2072727Sktlim@umich.edu    // Check if ROB is done squashing.
2082301SN/A    if ((*squashIt)->seqNum == squashedSeqNum) {
2092727Sktlim@umich.edu        DPRINTF(ROB, "ROB: Done squashing instructions.\n");
2106221Snate@binkert.org
2112301SN/A        squashIt = cpu->instList.end();
2122301SN/A
2132727Sktlim@umich.edu        doneSquashing = true;
2142301SN/A    }
2152301SN/A}
2162301SN/A
2172301SN/Atemplate <class Impl>
2182727Sktlim@umich.eduvoid
2192727Sktlim@umich.eduROB<Impl>::squash(InstSeqNum squash_num)
2202727Sktlim@umich.edu{
2212727Sktlim@umich.edu    DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n");
2222727Sktlim@umich.edu    doneSquashing = false;
2232727Sktlim@umich.edu
2242727Sktlim@umich.edu    squashedSeqNum = squash_num;
2252727Sktlim@umich.edu
2262727Sktlim@umich.edu    assert(tail != cpu->instList.end());
2272301SN/A
2282301SN/A    squashIt = tail;
2296221Snate@binkert.org
2302301SN/A    doSquash();
2312301SN/A}
2322727Sktlim@umich.edu
2332301SN/Atemplate <class Impl>
2342326SN/Auint64_t
2356221Snate@binkert.orgROB<Impl>::readHeadPC()
2362301SN/A{
2372301SN/A    assert(numInstsInROB == countInsts());
2382727Sktlim@umich.edu
2392301SN/A    DynInstPtr head_inst = cpu->instList.front();
2402326SN/A
2416221Snate@binkert.org    return head_inst->readPC();
2422301SN/A}
2432301SN/A
2442727Sktlim@umich.edutemplate <class Impl>
2452301SN/Auint64_t
2462326SN/AROB<Impl>::readHeadNextPC()
2476221Snate@binkert.org{
2482301SN/A    assert(numInstsInROB == countInsts());
2492301SN/A
2502727Sktlim@umich.edu    DynInstPtr head_inst = cpu->instList.front();
2512301SN/A
2522326SN/A    return head_inst->readNextPC();
2536221Snate@binkert.org}
2542301SN/A
2552301SN/Atemplate <class Impl>
2562727Sktlim@umich.eduInstSeqNum
2572301SN/AROB<Impl>::readHeadSeqNum()
2582326SN/A{
2592301SN/A    // Return the last sequence number that has not been squashed.  Other
2602301SN/A    // stages can use it to squash any instructions younger than the current
2612727Sktlim@umich.edu    // tail.
2622301SN/A    DynInstPtr head_inst = cpu->instList.front();
2632326SN/A
2642301SN/A    return head_inst->seqNum;
2652326SN/A}
2662301SN/A
2672301SN/Atemplate <class Impl>
2682727Sktlim@umich.eduuint64_t
2692301SN/AROB<Impl>::readTailPC()
2702326SN/A{
2712301SN/A    assert(numInstsInROB == countInsts());
2722326SN/A
2732301SN/A    assert(tail != cpu->instList.end());
2742301SN/A
2752727Sktlim@umich.edu    return (*tail)->readPC();
2762326SN/A}
2771062SN/A
2781062SN/Atemplate <class Impl>
2791681SN/AInstSeqNum
2801060SN/AROB<Impl>::readTailSeqNum()
2812292SN/A{
2821060SN/A    // Return the last sequence number that has not been squashed.  Other
2836221Snate@binkert.org    // stages can use it to squash any instructions younger than the current
2842292SN/A    // tail.
2852292SN/A    return (*tail)->seqNum;
2862292SN/A}
2872292SN/A
2882292SN/A#endif // __ROB_IMPL_HH__
2892292SN/A