rob_impl.hh revision 1061
12623SN/A#ifndef __ROB_IMPL_HH__
27725SAli.Saidi@ARM.com#define __ROB_IMPL_HH__
37725SAli.Saidi@ARM.com
47725SAli.Saidi@ARM.com#include "cpu/beta_cpu/rob.hh"
57725SAli.Saidi@ARM.com
67725SAli.Saidi@ARM.comtemplate <class Impl>
77725SAli.Saidi@ARM.comROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth)
87725SAli.Saidi@ARM.com    : numEntries(_numEntries),
97725SAli.Saidi@ARM.com      squashWidth(_squashWidth),
107725SAli.Saidi@ARM.com      numInstsInROB(0),
117725SAli.Saidi@ARM.com      squashedSeqNum(0)
127725SAli.Saidi@ARM.com{
137725SAli.Saidi@ARM.com    doneSquashing = true;
142623SN/A}
152623SN/A
162623SN/Atemplate <class Impl>
172623SN/Avoid
182623SN/AROB<Impl>::setCPU(FullCPU *cpu_ptr)
192623SN/A{
202623SN/A    cpu = cpu_ptr;
212623SN/A
222623SN/A    // Set the tail to the beginning of the CPU instruction list so that
232623SN/A    // upon the first instruction being inserted into the ROB, the tail
242623SN/A    // iterator can simply be incremented.
252623SN/A    tail = cpu->instList.begin();
262623SN/A
272623SN/A    // Set the squash iterator to the end of the instruction list.
282623SN/A    squashIt = cpu->instList.end();
292623SN/A}
302623SN/A
312623SN/Atemplate <class Impl>
322623SN/Aint
332623SN/AROB<Impl>::countInsts()
342623SN/A{
352623SN/A    // Start at 1; if the tail matches cpu->instList.begin(), then there is
362623SN/A    // one inst in the ROB.
372623SN/A    int return_val = 1;
382623SN/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.
412623SN/A    if (cpu->instList.begin() == cpu->instList.end()) {
422623SN/A        // In this case there are no instructions in the list.  The ROB
433170Sstever@eecs.umich.edu        // must be empty.
448105Sgblack@eecs.umich.edu        return 0;
452623SN/A    } else if (tail == cpu->instList.end()) {
464040Ssaidi@eecs.umich.edu        // In this case, the tail is not yet pointing to anything valid.
476658Snate@binkert.org        // The ROB must be empty.
488229Snate@binkert.org        return 0;
492623SN/A    }
503348Sbinkertn@umich.edu
513348Sbinkertn@umich.edu    // Iterate through the ROB from the head to the tail, counting the
524762Snate@binkert.org    // entries.
537678Sgblack@eecs.umich.edu    for (InstIt_t i = cpu->instList.begin(); i != tail; ++i)
542901Ssaidi@eecs.umich.edu    {
552623SN/A        assert(i != cpu->instList.end());
562623SN/A        ++return_val;
572623SN/A    }
582623SN/A
592856Srdreslin@umich.edu    return return_val;
602856Srdreslin@umich.edu
612856Srdreslin@umich.edu    // Because the head won't be tracked properly until the ROB gets the
622856Srdreslin@umich.edu    // first instruction, and any time that the ROB is empty and has not
632856Srdreslin@umich.edu    // yet gotten the instruction, this function doesn't work.
642856Srdreslin@umich.edu//    return numInstsInROB;
652856Srdreslin@umich.edu}
662856Srdreslin@umich.edu
672856Srdreslin@umich.edutemplate <class Impl>
682856Srdreslin@umich.eduvoid
692623SN/AROB<Impl>::insertInst(DynInstPtr &inst)
702623SN/A{
712623SN/A    // Make sure we have the right number of instructions.
722623SN/A    assert(numInstsInROB == countInsts());
732623SN/A    // Make sure the instruction is valid.
742623SN/A    assert(inst);
752680Sktlim@umich.edu
762680Sktlim@umich.edu    DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC());
772623SN/A
782623SN/A    // If the ROB is full then exit.
795712Shsul@eecs.umich.edu    assert(numInstsInROB != numEntries);
802623SN/A
812623SN/A    ++numInstsInROB;
822623SN/A
832623SN/A    // Increment the tail iterator, moving it one instruction back.
842623SN/A    // There is a special case if the ROB was empty prior to this insertion,
853349Sbinkertn@umich.edu    // in which case the tail will be pointing at instList.end().  If that
862623SN/A    // happens, then reset the tail to the beginning of the list.
872623SN/A    if (tail != cpu->instList.end()) {
887823Ssteve.reinhardt@amd.com        ++tail;
892623SN/A    } else {
902623SN/A        tail = cpu->instList.begin();
912623SN/A    }
923349Sbinkertn@umich.edu
932623SN/A    // Make sure the tail iterator is actually pointing at the instruction
943184Srdreslin@umich.edu    // added.
953184Srdreslin@umich.edu    assert((*tail) == inst);
962623SN/A
972623SN/A    DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB);
982623SN/A
992623SN/A}
1002623SN/A
1013647Srdreslin@umich.edu// Whatever calls this function needs to ensure that it properly frees up
1023647Srdreslin@umich.edu// registers prior to this function.
1033647Srdreslin@umich.edutemplate <class Impl>
1043647Srdreslin@umich.eduvoid
1053647Srdreslin@umich.eduROB<Impl>::retireHead()
1062631SN/A{
1073647Srdreslin@umich.edu    assert(numInstsInROB == countInsts());
1082631SN/A    assert(numInstsInROB > 0);
1092623SN/A
1102623SN/A    DynInstPtr head_inst;
1112623SN/A
1122948Ssaidi@eecs.umich.edu    // Get the head ROB instruction.
1132948Ssaidi@eecs.umich.edu    head_inst = cpu->instList.front();
1143349Sbinkertn@umich.edu
1152948Ssaidi@eecs.umich.edu    // Make certain this can retire.
1162948Ssaidi@eecs.umich.edu    assert(head_inst->readyToCommit());
1175606Snate@binkert.org
1182948Ssaidi@eecs.umich.edu    DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, "
1192948Ssaidi@eecs.umich.edu            "instruction PC %#x, seq num %i\n", head_inst->readPC(),
1205529Snate@binkert.org            head_inst->seqNum);
1215894Sgblack@eecs.umich.edu
1225894Sgblack@eecs.umich.edu    // Keep track of how many instructions are in the ROB.
1232623SN/A    --numInstsInROB;
1242623SN/A
1253647Srdreslin@umich.edu    // Tell CPU to remove the instruction from the list of instructions.
1263647Srdreslin@umich.edu    // A special case is needed if the instruction being retired is the
1273647Srdreslin@umich.edu    // only instruction in the ROB; otherwise the tail iterator will become
1283647Srdreslin@umich.edu    // invalidated.
1292623SN/A    if (tail == cpu->instList.begin()) {
1302839Sktlim@umich.edu        cpu->removeFrontInst(head_inst);
1313222Sktlim@umich.edu        tail = cpu->instList.end();
1322901Ssaidi@eecs.umich.edu    } else {
1337897Shestness@cs.utexas.edu        cpu->removeFrontInst(head_inst);
1342623SN/A    }
1352623SN/A}
1362623SN/A
1372623SN/Atemplate <class Impl>
1382623SN/Abool
1392623SN/AROB<Impl>::isHeadReady()
1402623SN/A{
1412623SN/A    if (numInstsInROB != 0) {
1422623SN/A        DynInstPtr head_inst = cpu->instList.front();
1432623SN/A
1442915Sktlim@umich.edu        return head_inst->readyToCommit();
1452915Sktlim@umich.edu    }
1462623SN/A
1472623SN/A    return false;
1482623SN/A}
1492623SN/A
1502623SN/Atemplate <class Impl>
1512623SN/Aunsigned
1522915Sktlim@umich.eduROB<Impl>::numFreeEntries()
1532915Sktlim@umich.edu{
1542623SN/A    assert(numInstsInROB == countInsts());
1552798Sktlim@umich.edu
1562798Sktlim@umich.edu    return numEntries - numInstsInROB;
1572901Ssaidi@eecs.umich.edu}
1582839Sktlim@umich.edu
1592798Sktlim@umich.edutemplate <class Impl>
1602839Sktlim@umich.eduvoid
1612798Sktlim@umich.eduROB<Impl>::doSquash()
1625496Ssaidi@eecs.umich.edu{
1632901Ssaidi@eecs.umich.edu    DPRINTF(ROB, "ROB: Squashing instructions.\n");
1642901Ssaidi@eecs.umich.edu
1652798Sktlim@umich.edu    assert(squashIt != cpu->instList.end());
1662839Sktlim@umich.edu
1672839Sktlim@umich.edu    for (int numSquashed = 0;
1682901Ssaidi@eecs.umich.edu         numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum;
1692798Sktlim@umich.edu         ++numSquashed)
1702623SN/A    {
1712623SN/A        // Ensure that the instruction is younger.
1722623SN/A        assert((*squashIt)->seqNum > squashedSeqNum);
1732798Sktlim@umich.edu
1742623SN/A        DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n",
1755221Ssaidi@eecs.umich.edu                (*squashIt)->readPC(), (*squashIt)->seqNum);
1762798Sktlim@umich.edu
1774762Snate@binkert.org        // Mark the instruction as squashed, and ready to commit so that
1783201Shsul@eecs.umich.edu        // it can drain out of the pipeline.
1795710Scws3k@cs.virginia.edu        (*squashIt)->setSquashed();
1805710Scws3k@cs.virginia.edu
1812915Sktlim@umich.edu        (*squashIt)->setCanCommit();
1825710Scws3k@cs.virginia.edu
1832623SN/A        // Special case for when squashing due to a syscall.  It's possible
1842798Sktlim@umich.edu        // that the squash happened after the head instruction was already
1852901Ssaidi@eecs.umich.edu        // committed, meaning that (*squashIt)->seqNum != squashedSeqNum
1862798Sktlim@umich.edu        // will never be false.  Normally the squash would never be able
1872798Sktlim@umich.edu        // to go past the head of the ROB; in this case it might, so it
1882798Sktlim@umich.edu        // must be handled otherwise it will segfault.
1892798Sktlim@umich.edu#ifndef FULL_SYSTEM
1902798Sktlim@umich.edu        if (squashIt == cpu->instList.begin()) {
1915496Ssaidi@eecs.umich.edu            DPRINTF(ROB, "ROB: Reached head of instruction list while "
1922798Sktlim@umich.edu                    "squashing.\n");
1937823Ssteve.reinhardt@amd.com
1942867Sktlim@umich.edu            squashIt = cpu->instList.end();
1952867Sktlim@umich.edu
1962867Sktlim@umich.edu            doneSquashing = true;
1975710Scws3k@cs.virginia.edu
1985606Snate@binkert.org            return;
1992623SN/A        }
2002623SN/A#endif
2012623SN/A
2022623SN/A        // Move the tail iterator to the next instruction.
2032623SN/A        squashIt--;
2042623SN/A    }
2054192Sktlim@umich.edu
2062623SN/A
2072680Sktlim@umich.edu    // Check if ROB is done squashing.
2082623SN/A    if ((*squashIt)->seqNum == squashedSeqNum) {
2092680Sktlim@umich.edu        DPRINTF(ROB, "ROB: Done squashing instructions.\n");
2102680Sktlim@umich.edu
2112680Sktlim@umich.edu        squashIt = cpu->instList.end();
2122623SN/A
2132623SN/A        doneSquashing = true;
2142623SN/A    }
2152623SN/A}
2163201Shsul@eecs.umich.edu
2173201Shsul@eecs.umich.edutemplate <class Impl>
2183201Shsul@eecs.umich.eduvoid
2193201Shsul@eecs.umich.eduROB<Impl>::squash(InstSeqNum squash_num)
2205169Ssaidi@eecs.umich.edu{
2217823Ssteve.reinhardt@amd.com    DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n");
2222623SN/A    doneSquashing = false;
2232623SN/A
2242623SN/A    squashedSeqNum = squash_num;
2252623SN/A
2262623SN/A    assert(tail != cpu->instList.end());
2272623SN/A
2285221Ssaidi@eecs.umich.edu    squashIt = tail;
2295221Ssaidi@eecs.umich.edu
2302623SN/A    doSquash();
2312683Sktlim@umich.edu}
2322623SN/A
2332623SN/Atemplate <class Impl>
2342623SN/Auint64_t
2352623SN/AROB<Impl>::readHeadPC()
2362623SN/A{
2373686Sktlim@umich.edu    assert(numInstsInROB == countInsts());
2382623SN/A
2397823Ssteve.reinhardt@amd.com    DynInstPtr head_inst = cpu->instList.front();
2402623SN/A
2412623SN/A    return head_inst->readPC();
2422623SN/A}
2432623SN/A
2442623SN/Atemplate <class Impl>
2452623SN/Auint64_t
2465221Ssaidi@eecs.umich.eduROB<Impl>::readHeadNextPC()
2475221Ssaidi@eecs.umich.edu{
2482623SN/A    assert(numInstsInROB == countInsts());
2492683Sktlim@umich.edu
2502623SN/A    DynInstPtr head_inst = cpu->instList.front();
2516043Sgblack@eecs.umich.edu
2526043Sgblack@eecs.umich.edu    return head_inst->readNextPC();
2536043Sgblack@eecs.umich.edu}
2542644Sstever@eecs.umich.edu
2552623SN/Atemplate <class Impl>
2562644Sstever@eecs.umich.eduInstSeqNum
2572644Sstever@eecs.umich.eduROB<Impl>::readHeadSeqNum()
2582623SN/A{
2592623SN/A    // Return the last sequence number that has not been squashed.  Other
2602623SN/A    // stages can use it to squash any instructions younger than the current
2612623SN/A    // tail.
2622623SN/A    DynInstPtr head_inst = cpu->instList.front();
2635728Sgblack@eecs.umich.edu
2645728Sgblack@eecs.umich.edu    return head_inst->seqNum;
2655728Sgblack@eecs.umich.edu}
2665728Sgblack@eecs.umich.edu
2678105Sgblack@eecs.umich.edutemplate <class Impl>
2685728Sgblack@eecs.umich.eduuint64_t
2695728Sgblack@eecs.umich.eduROB<Impl>::readTailPC()
2707823Ssteve.reinhardt@amd.com{
2715728Sgblack@eecs.umich.edu    assert(numInstsInROB == countInsts());
2725728Sgblack@eecs.umich.edu
2735728Sgblack@eecs.umich.edu    assert(tail != cpu->instList.end());
2745728Sgblack@eecs.umich.edu
2755728Sgblack@eecs.umich.edu    return (*tail)->readPC();
2765728Sgblack@eecs.umich.edu}
2775728Sgblack@eecs.umich.edu
2785728Sgblack@eecs.umich.edutemplate <class Impl>
2795728Sgblack@eecs.umich.eduInstSeqNum
2805728Sgblack@eecs.umich.eduROB<Impl>::readTailSeqNum()
2815728Sgblack@eecs.umich.edu{
2825728Sgblack@eecs.umich.edu    // Return the last sequence number that has not been squashed.  Other
2832623SN/A    // stages can use it to squash any instructions younger than the current
2845894Sgblack@eecs.umich.edu    // tail.
2856973Stjones1@inf.ed.ac.uk    return (*tail)->seqNum;
2866973Stjones1@inf.ed.ac.uk}
2875744Sgblack@eecs.umich.edu
2885894Sgblack@eecs.umich.edu#endif // __ROB_IMPL_HH__
2895894Sgblack@eecs.umich.edu