rob_impl.hh revision 1681
14120Sgblack@eecs.umich.edu#ifndef __CPU_BETA_CPU_ROB_IMPL_HH__
24120Sgblack@eecs.umich.edu#define __CPU_BETA_CPU_ROB_IMPL_HH__
34120Sgblack@eecs.umich.edu
44120Sgblack@eecs.umich.edu#include "cpu/beta_cpu/rob.hh"
57087Snate@binkert.org
67087Snate@binkert.orgtemplate <class Impl>
77087Snate@binkert.orgROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth)
87087Snate@binkert.org    : numEntries(_numEntries),
97087Snate@binkert.org      squashWidth(_squashWidth),
107087Snate@binkert.org      numInstsInROB(0),
117087Snate@binkert.org      squashedSeqNum(0)
127087Snate@binkert.org{
134120Sgblack@eecs.umich.edu    doneSquashing = true;
147087Snate@binkert.org}
157087Snate@binkert.org
167087Snate@binkert.orgtemplate <class Impl>
177087Snate@binkert.orgvoid
187087Snate@binkert.orgROB<Impl>::setCPU(FullCPU *cpu_ptr)
197087Snate@binkert.org{
207087Snate@binkert.org    cpu = cpu_ptr;
217087Snate@binkert.org
224120Sgblack@eecs.umich.edu    // Set the tail to the beginning of the CPU instruction list so that
237087Snate@binkert.org    // upon the first instruction being inserted into the ROB, the tail
244120Sgblack@eecs.umich.edu    // iterator can simply be incremented.
254120Sgblack@eecs.umich.edu    tail = cpu->instList.begin();
264120Sgblack@eecs.umich.edu
274120Sgblack@eecs.umich.edu    // Set the squash iterator to the end of the instruction list.
284120Sgblack@eecs.umich.edu    squashIt = cpu->instList.end();
294120Sgblack@eecs.umich.edu}
304120Sgblack@eecs.umich.edu
314120Sgblack@eecs.umich.edutemplate <class Impl>
324120Sgblack@eecs.umich.eduint
334120Sgblack@eecs.umich.eduROB<Impl>::countInsts()
344120Sgblack@eecs.umich.edu{
354120Sgblack@eecs.umich.edu    // Start at 1; if the tail matches cpu->instList.begin(), then there is
364120Sgblack@eecs.umich.edu    // one inst in the ROB.
374120Sgblack@eecs.umich.edu    int return_val = 1;
384120Sgblack@eecs.umich.edu
394120Sgblack@eecs.umich.edu    // There are quite a few special cases.  Do not use this function other
404120Sgblack@eecs.umich.edu    // than for debugging purposes.
414120Sgblack@eecs.umich.edu    if (cpu->instList.begin() == cpu->instList.end()) {
424120Sgblack@eecs.umich.edu        // In this case there are no instructions in the list.  The ROB
435857Sgblack@eecs.umich.edu        // must be empty.
444139Sgblack@eecs.umich.edu        return 0;
454135Sgblack@eecs.umich.edu    } else if (tail == cpu->instList.end()) {
466023Snate@binkert.org        // In this case, the tail is not yet pointing to anything valid.
474120Sgblack@eecs.umich.edu        // The ROB must be empty.
485909Sgblack@eecs.umich.edu        return 0;
495909Sgblack@eecs.umich.edu    }
504120Sgblack@eecs.umich.edu
514120Sgblack@eecs.umich.edu    // Iterate through the ROB from the head to the tail, counting the
525114Sgblack@eecs.umich.edu    // entries.
535114Sgblack@eecs.umich.edu    for (InstIt_t i = cpu->instList.begin(); i != tail; ++i)
544135Sgblack@eecs.umich.edu    {
554365Sgblack@eecs.umich.edu        assert(i != cpu->instList.end());
565114Sgblack@eecs.umich.edu        ++return_val;
575114Sgblack@eecs.umich.edu    }
585851Sgblack@eecs.umich.edu
595139Sgblack@eecs.umich.edu    return return_val;
605114Sgblack@eecs.umich.edu
615139Sgblack@eecs.umich.edu    // Because the head won't be tracked properly until the ROB gets the
626009Snate@binkert.org    // first instruction, and any time that the ROB is empty and has not
636009Snate@binkert.org    // yet gotten the instruction, this function doesn't work.
646009Snate@binkert.org//    return numInstsInROB;
655114Sgblack@eecs.umich.edu}
665114Sgblack@eecs.umich.edu
675114Sgblack@eecs.umich.edutemplate <class Impl>
684729Sgblack@eecs.umich.eduvoid
694365Sgblack@eecs.umich.eduROB<Impl>::insertInst(DynInstPtr &inst)
705114Sgblack@eecs.umich.edu{
714365Sgblack@eecs.umich.edu    // Make sure we have the right number of instructions.
724365Sgblack@eecs.umich.edu    assert(numInstsInROB == countInsts());
735114Sgblack@eecs.umich.edu    // Make sure the instruction is valid.
745114Sgblack@eecs.umich.edu    assert(inst);
755114Sgblack@eecs.umich.edu
765114Sgblack@eecs.umich.edu    DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC());
775114Sgblack@eecs.umich.edu
785114Sgblack@eecs.umich.edu    // If the ROB is full then exit.
795114Sgblack@eecs.umich.edu    assert(numInstsInROB != numEntries);
805114Sgblack@eecs.umich.edu
815114Sgblack@eecs.umich.edu    ++numInstsInROB;
825684Sgblack@eecs.umich.edu
835858Sgblack@eecs.umich.edu    // Increment the tail iterator, moving it one instruction back.
845684Sgblack@eecs.umich.edu    // There is a special case if the ROB was empty prior to this insertion,
855858Sgblack@eecs.umich.edu    // in which case the tail will be pointing at instList.end().  If that
865684Sgblack@eecs.umich.edu    // happens, then reset the tail to the beginning of the list.
875858Sgblack@eecs.umich.edu    if (tail != cpu->instList.end()) {
885858Sgblack@eecs.umich.edu        ++tail;
895858Sgblack@eecs.umich.edu    } else {
905909Sgblack@eecs.umich.edu        tail = cpu->instList.begin();
915909Sgblack@eecs.umich.edu    }
925858Sgblack@eecs.umich.edu
935114Sgblack@eecs.umich.edu    // Make sure the tail iterator is actually pointing at the instruction
945114Sgblack@eecs.umich.edu    // added.
955114Sgblack@eecs.umich.edu    assert((*tail) == inst);
965114Sgblack@eecs.umich.edu
975114Sgblack@eecs.umich.edu    DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB);
985114Sgblack@eecs.umich.edu
995114Sgblack@eecs.umich.edu}
1005139Sgblack@eecs.umich.edu
1016009Snate@binkert.org// Whatever calls this function needs to ensure that it properly frees up
1026009Snate@binkert.org// registers prior to this function.
1035114Sgblack@eecs.umich.edutemplate <class Impl>
1045114Sgblack@eecs.umich.eduvoid
1055114Sgblack@eecs.umich.eduROB<Impl>::retireHead()
1065114Sgblack@eecs.umich.edu{
1075114Sgblack@eecs.umich.edu    assert(numInstsInROB == countInsts());
1085114Sgblack@eecs.umich.edu    assert(numInstsInROB > 0);
1095114Sgblack@eecs.umich.edu
1105114Sgblack@eecs.umich.edu    // Get the head ROB instruction.
1115139Sgblack@eecs.umich.edu    DynInstPtr head_inst = cpu->instList.front();
1126009Snate@binkert.org
1136009Snate@binkert.org    // Make certain this can retire.
1145114Sgblack@eecs.umich.edu    assert(head_inst->readyToCommit());
1155114Sgblack@eecs.umich.edu
1165114Sgblack@eecs.umich.edu    DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, "
1175124Sgblack@eecs.umich.edu            "instruction PC %#x, seq num %i\n", head_inst->readPC(),
1185114Sgblack@eecs.umich.edu            head_inst->seqNum);
1195114Sgblack@eecs.umich.edu
1205114Sgblack@eecs.umich.edu    // Keep track of how many instructions are in the ROB.
1215114Sgblack@eecs.umich.edu    --numInstsInROB;
1225114Sgblack@eecs.umich.edu
1235114Sgblack@eecs.umich.edu    // Tell CPU to remove the instruction from the list of instructions.
1245114Sgblack@eecs.umich.edu    // A special case is needed if the instruction being retired is the
1255139Sgblack@eecs.umich.edu    // only instruction in the ROB; otherwise the tail iterator will become
1266009Snate@binkert.org    // invalidated.
1276009Snate@binkert.org    cpu->removeFrontInst(head_inst);
1285114Sgblack@eecs.umich.edu
1295114Sgblack@eecs.umich.edu    if (numInstsInROB == 0) {
1305114Sgblack@eecs.umich.edu        tail = cpu->instList.end();
1315124Sgblack@eecs.umich.edu    }
1325114Sgblack@eecs.umich.edu}
1335114Sgblack@eecs.umich.edu
1345114Sgblack@eecs.umich.edutemplate <class Impl>
1355114Sgblack@eecs.umich.edubool
1365114Sgblack@eecs.umich.eduROB<Impl>::isHeadReady()
1375114Sgblack@eecs.umich.edu{
1385114Sgblack@eecs.umich.edu    if (numInstsInROB != 0) {
1395851Sgblack@eecs.umich.edu        return cpu->instList.front()->readyToCommit();
1406009Snate@binkert.org    }
1416009Snate@binkert.org
1425114Sgblack@eecs.umich.edu    return false;
1434135Sgblack@eecs.umich.edu}
1444150Sgblack@eecs.umich.edu
1454365Sgblack@eecs.umich.edutemplate <class Impl>
1464365Sgblack@eecs.umich.eduunsigned
1474365Sgblack@eecs.umich.eduROB<Impl>::numFreeEntries()
1484729Sgblack@eecs.umich.edu{
1494365Sgblack@eecs.umich.edu    assert(numInstsInROB == countInsts());
1504365Sgblack@eecs.umich.edu
1514365Sgblack@eecs.umich.edu    return numEntries - numInstsInROB;
1524365Sgblack@eecs.umich.edu}
1534365Sgblack@eecs.umich.edu
1544365Sgblack@eecs.umich.edutemplate <class Impl>
1554365Sgblack@eecs.umich.eduvoid
1564365Sgblack@eecs.umich.eduROB<Impl>::doSquash()
1574365Sgblack@eecs.umich.edu{
1584365Sgblack@eecs.umich.edu    DPRINTF(ROB, "ROB: Squashing instructions.\n");
1594150Sgblack@eecs.umich.edu
1604150Sgblack@eecs.umich.edu    assert(squashIt != cpu->instList.end());
1614150Sgblack@eecs.umich.edu
1624150Sgblack@eecs.umich.edu    for (int numSquashed = 0;
1635114Sgblack@eecs.umich.edu         numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum;
1645114Sgblack@eecs.umich.edu         ++numSquashed)
1655114Sgblack@eecs.umich.edu    {
1665114Sgblack@eecs.umich.edu        // Ensure that the instruction is younger.
1675114Sgblack@eecs.umich.edu        assert((*squashIt)->seqNum > squashedSeqNum);
1685114Sgblack@eecs.umich.edu
1695114Sgblack@eecs.umich.edu        DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n",
1705114Sgblack@eecs.umich.edu                (*squashIt)->readPC(), (*squashIt)->seqNum);
1715114Sgblack@eecs.umich.edu
1725114Sgblack@eecs.umich.edu        // Mark the instruction as squashed, and ready to commit so that
1735114Sgblack@eecs.umich.edu        // it can drain out of the pipeline.
1745114Sgblack@eecs.umich.edu        (*squashIt)->setSquashed();
1755114Sgblack@eecs.umich.edu
1765114Sgblack@eecs.umich.edu        (*squashIt)->setCanCommit();
1775114Sgblack@eecs.umich.edu
1785114Sgblack@eecs.umich.edu        // Special case for when squashing due to a syscall.  It's possible
1795114Sgblack@eecs.umich.edu        // that the squash happened after the head instruction was already
1805114Sgblack@eecs.umich.edu        // committed, meaning that (*squashIt)->seqNum != squashedSeqNum
1815114Sgblack@eecs.umich.edu        // will never be false.  Normally the squash would never be able
1825114Sgblack@eecs.umich.edu        // to go past the head of the ROB; in this case it might, so it
1835114Sgblack@eecs.umich.edu        // must be handled otherwise it will segfault.
1845114Sgblack@eecs.umich.edu#ifndef FULL_SYSTEM
1855114Sgblack@eecs.umich.edu        if (squashIt == cpu->instList.begin()) {
1865114Sgblack@eecs.umich.edu            DPRINTF(ROB, "ROB: Reached head of instruction list while "
1875114Sgblack@eecs.umich.edu                    "squashing.\n");
1885114Sgblack@eecs.umich.edu
1895114Sgblack@eecs.umich.edu            squashIt = cpu->instList.end();
1905114Sgblack@eecs.umich.edu
1915114Sgblack@eecs.umich.edu            doneSquashing = true;
1925114Sgblack@eecs.umich.edu
1935114Sgblack@eecs.umich.edu            return;
1945114Sgblack@eecs.umich.edu        }
1955114Sgblack@eecs.umich.edu#endif
1965114Sgblack@eecs.umich.edu
1975114Sgblack@eecs.umich.edu        // Move the tail iterator to the next instruction.
1985114Sgblack@eecs.umich.edu        squashIt--;
1995851Sgblack@eecs.umich.edu    }
2005114Sgblack@eecs.umich.edu
2015114Sgblack@eecs.umich.edu
2025114Sgblack@eecs.umich.edu    // Check if ROB is done squashing.
2035114Sgblack@eecs.umich.edu    if ((*squashIt)->seqNum == squashedSeqNum) {
2045114Sgblack@eecs.umich.edu        DPRINTF(ROB, "ROB: Done squashing instructions.\n");
2055114Sgblack@eecs.umich.edu
2065114Sgblack@eecs.umich.edu        squashIt = cpu->instList.end();
2075851Sgblack@eecs.umich.edu
2085114Sgblack@eecs.umich.edu        doneSquashing = true;
2095114Sgblack@eecs.umich.edu    }
2105114Sgblack@eecs.umich.edu}
2115114Sgblack@eecs.umich.edu
2125114Sgblack@eecs.umich.edutemplate <class Impl>
2135114Sgblack@eecs.umich.eduvoid
2145655Sgblack@eecs.umich.eduROB<Impl>::squash(InstSeqNum squash_num)
2155851Sgblack@eecs.umich.edu{
2165114Sgblack@eecs.umich.edu    DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n");
2175114Sgblack@eecs.umich.edu    doneSquashing = false;
2185114Sgblack@eecs.umich.edu
2195114Sgblack@eecs.umich.edu    squashedSeqNum = squash_num;
2205114Sgblack@eecs.umich.edu
2215114Sgblack@eecs.umich.edu    assert(tail != cpu->instList.end());
2225114Sgblack@eecs.umich.edu
2235851Sgblack@eecs.umich.edu    squashIt = tail;
2245114Sgblack@eecs.umich.edu
2255114Sgblack@eecs.umich.edu    doSquash();
2265114Sgblack@eecs.umich.edu}
2275114Sgblack@eecs.umich.edu
2285114Sgblack@eecs.umich.edutemplate <class Impl>
2295114Sgblack@eecs.umich.eduuint64_t
2305114Sgblack@eecs.umich.eduROB<Impl>::readHeadPC()
2315851Sgblack@eecs.umich.edu{
2325114Sgblack@eecs.umich.edu    assert(numInstsInROB == countInsts());
2335114Sgblack@eecs.umich.edu
2345114Sgblack@eecs.umich.edu    DynInstPtr head_inst = cpu->instList.front();
2355114Sgblack@eecs.umich.edu
2365114Sgblack@eecs.umich.edu    return head_inst->readPC();
2375114Sgblack@eecs.umich.edu}
2385114Sgblack@eecs.umich.edu
2395851Sgblack@eecs.umich.edutemplate <class Impl>
2405114Sgblack@eecs.umich.eduuint64_t
2415114Sgblack@eecs.umich.eduROB<Impl>::readHeadNextPC()
2425114Sgblack@eecs.umich.edu{
2435114Sgblack@eecs.umich.edu    assert(numInstsInROB == countInsts());
2445114Sgblack@eecs.umich.edu
2455114Sgblack@eecs.umich.edu    DynInstPtr head_inst = cpu->instList.front();
2465114Sgblack@eecs.umich.edu
2475851Sgblack@eecs.umich.edu    return head_inst->readNextPC();
2485114Sgblack@eecs.umich.edu}
2495114Sgblack@eecs.umich.edu
2505114Sgblack@eecs.umich.edutemplate <class Impl>
2515114Sgblack@eecs.umich.eduInstSeqNum
2525114Sgblack@eecs.umich.eduROB<Impl>::readHeadSeqNum()
2535114Sgblack@eecs.umich.edu{
2545114Sgblack@eecs.umich.edu    // Return the last sequence number that has not been squashed.  Other
2555851Sgblack@eecs.umich.edu    // stages can use it to squash any instructions younger than the current
2565114Sgblack@eecs.umich.edu    // tail.
2575114Sgblack@eecs.umich.edu    DynInstPtr head_inst = cpu->instList.front();
2585114Sgblack@eecs.umich.edu
2595114Sgblack@eecs.umich.edu    return head_inst->seqNum;
2605114Sgblack@eecs.umich.edu}
2615114Sgblack@eecs.umich.edu
2625114Sgblack@eecs.umich.edutemplate <class Impl>
2635857Sgblack@eecs.umich.eduuint64_t
2645114Sgblack@eecs.umich.eduROB<Impl>::readTailPC()
2655114Sgblack@eecs.umich.edu{
2665114Sgblack@eecs.umich.edu    assert(numInstsInROB == countInsts());
2675114Sgblack@eecs.umich.edu
2685114Sgblack@eecs.umich.edu    assert(tail != cpu->instList.end());
2695114Sgblack@eecs.umich.edu
2705857Sgblack@eecs.umich.edu    return (*tail)->readPC();
2715857Sgblack@eecs.umich.edu}
2725114Sgblack@eecs.umich.edu
2735114Sgblack@eecs.umich.edutemplate <class Impl>
2745114Sgblack@eecs.umich.eduInstSeqNum
2755114Sgblack@eecs.umich.eduROB<Impl>::readTailSeqNum()
2765114Sgblack@eecs.umich.edu{
2775114Sgblack@eecs.umich.edu    // Return the last sequence number that has not been squashed.  Other
2785857Sgblack@eecs.umich.edu    // stages can use it to squash any instructions younger than the current
2795857Sgblack@eecs.umich.edu    // tail.
2805114Sgblack@eecs.umich.edu    return (*tail)->seqNum;
2815114Sgblack@eecs.umich.edu}
2825114Sgblack@eecs.umich.edu
2835114Sgblack@eecs.umich.edu#endif // __CPU_BETA_CPU_ROB_IMPL_HH__
2845114Sgblack@eecs.umich.edu