rob_impl.hh revision 1060
12124SN/A#ifndef __ROB_IMPL_HH__
22124SN/A#define __ROB_IMPL_HH__
32754Sksewell@umich.edu
42124SN/A#include "cpu/beta_cpu/rob.hh"
52022SN/A
62124SN/Atemplate<class Impl>
72124SN/AROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth)
82124SN/A    : numEntries(_numEntries),
92124SN/A      squashWidth(_squashWidth),
102124SN/A      numInstsInROB(0),
112124SN/A      squashedSeqNum(0)
122124SN/A{
132124SN/A    doneSquashing = true;
142124SN/A}
152124SN/A
162022SN/Atemplate<class Impl>
172124SN/Avoid
182124SN/AROB<Impl>::setCPU(FullCPU *cpu_ptr)
192124SN/A{
202124SN/A    cpu = cpu_ptr;
212124SN/A
222124SN/A    tail = cpu->instList.begin();
232124SN/A
242124SN/A    squashIt = cpu->instList.end();
252124SN/A}
262124SN/A
272124SN/Atemplate<class Impl>
282665Ssaidi@eecs.umich.eduint
292935Sksewell@umich.eduROB<Impl>::countInsts()
302665Ssaidi@eecs.umich.edu{
312022SN/A/*
322649Ssaidi@eecs.umich.edu    int return_val = 0;
332649Ssaidi@eecs.umich.edu
342706Sksewell@umich.edu    // Iterate through the ROB from the head to the tail, counting the
352649Ssaidi@eecs.umich.edu    // entries.
362649Ssaidi@eecs.umich.edu    for (InstIt i = cpu->instList.begin(); i != tail; i++)
372022SN/A    {
382124SN/A        assert(i != cpu->instList.end());
392124SN/A        return_val++;
402124SN/A    }
412124SN/A
422124SN/A    return return_val;
432124SN/A*/
442124SN/A    // Because the head won't be tracked properly until the ROB gets the
452124SN/A    // first instruction, and any time that the ROB is empty and has not
462124SN/A    // yet gotten the instruction, this function doesn't work.
472124SN/A    return numInstsInROB;
482124SN/A}
492124SN/A
502124SN/Atemplate<class Impl>
512239SN/Avoid
522124SN/AROB<Impl>::insertInst(DynInst *inst)
532124SN/A{
542124SN/A    // Make sure we have the right number of instructions.
552124SN/A    assert(numInstsInROB == countInsts());
562124SN/A    // Make sure the instruction is valid.
572124SN/A    assert(inst);
582124SN/A
592124SN/A    DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC());
602124SN/A
612742Sksewell@umich.edu    // If the ROB is full then exit.
622022SN/A    assert(numInstsInROB != numEntries);
632124SN/A
642022SN/A    ++numInstsInROB;
652124SN/A
662124SN/A    // Increment the tail iterator, moving it one instruction back.
672022SN/A    // There is a special case if the ROB was empty prior to this insertion,
682124SN/A    // in which case the tail will be pointing at instList.end().  If that
692124SN/A    // happens, then reset the tail to the beginning of the list.
702124SN/A    if (tail != cpu->instList.end()) {
712124SN/A        tail++;
722124SN/A    } else {
732124SN/A        tail = cpu->instList.begin();
742742Sksewell@umich.edu    }
752742Sksewell@umich.edu
762742Sksewell@umich.edu    // Make sure the tail iterator is actually pointing at the instruction
772742Sksewell@umich.edu    // added.
782742Sksewell@umich.edu    assert((*tail) == inst);
792742Sksewell@umich.edu
802742Sksewell@umich.edu    DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB);
812742Sksewell@umich.edu
822742Sksewell@umich.edu}
832742Sksewell@umich.edu
842742Sksewell@umich.edu// Whatever calls this function needs to ensure that it properly frees up
852742Sksewell@umich.edu// registers prior to this function.
862742Sksewell@umich.edutemplate<class Impl>
872742Sksewell@umich.eduvoid
882742Sksewell@umich.eduROB<Impl>::retireHead()
892742Sksewell@umich.edu{
902742Sksewell@umich.edu    assert(numInstsInROB == countInsts());
912742Sksewell@umich.edu
922022SN/A    DynInst *head_inst;
932022SN/A
942124SN/A    // Get the head ROB instruction.
952022SN/A    head_inst = cpu->instList.front();
962124SN/A
972124SN/A    // Make certain this can retire.
982124SN/A    assert(head_inst->readyToCommit());
992742Sksewell@umich.edu
1002239SN/A    DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, "
1012124SN/A            "instruction PC %#x, seq num %i\n", head_inst->readPC(),
1022124SN/A            head_inst->seqNum);
1032742Sksewell@umich.edu
1042742Sksewell@umich.edu    // Keep track of how many instructions are in the ROB.
1052742Sksewell@umich.edu    --numInstsInROB;
1062742Sksewell@umich.edu
1072742Sksewell@umich.edu    // Tell CPU to remove the instruction from the list of instructions.
1082742Sksewell@umich.edu    // A special case is needed if the instruction being retired is the
1092742Sksewell@umich.edu    // only instruction in the ROB; otherwise the tail iterator will become
1102742Sksewell@umich.edu    // invalidated.
1112022SN/A    if (tail == cpu->instList.begin()) {
1122022SN/A        cpu->removeFrontInst(head_inst);
1132124SN/A        tail = cpu->instList.end();
1142124SN/A    } else {
1152124SN/A        cpu->removeFrontInst(head_inst);
1162124SN/A    }
1172124SN/A}
1182124SN/A
1192124SN/Atemplate<class Impl>
1202124SN/Abool
1212124SN/AROB<Impl>::isHeadReady()
1222124SN/A{
1232124SN/A    if (numInstsInROB != 0) {
1242124SN/A        DynInst *head_inst = cpu->instList.front();
1252124SN/A
1262124SN/A        return head_inst->readyToCommit();
1272124SN/A    }
1282124SN/A
1292124SN/A    return false;
1302124SN/A}
1312124SN/A
1322124SN/Atemplate<class Impl>
1332124SN/Aunsigned
1342124SN/AROB<Impl>::numFreeEntries()
1352124SN/A{
1362124SN/A    assert(numInstsInROB == countInsts());
1372124SN/A
1382124SN/A    return numEntries - numInstsInROB;
1392124SN/A}
1402124SN/A
1412124SN/Atemplate<class Impl>
1422124SN/Avoid
1432124SN/AROB<Impl>::doSquash()
1442124SN/A{
1452124SN/A    DPRINTF(ROB, "ROB: Squashing instructions.\n");
1462124SN/A
1472124SN/A    assert(squashIt != cpu->instList.end());
1482124SN/A
1492124SN/A    for (int numSquashed = 0;
1502124SN/A         numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum;
1512124SN/A         ++numSquashed)
1522124SN/A    {
1532124SN/A        // Ensure that the instruction is younger.
1542124SN/A        assert((*squashIt)->seqNum > squashedSeqNum);
1552124SN/A
1562022SN/A        DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n",
1572022SN/A                (*squashIt)->readPC(), (*squashIt)->seqNum);
1582124SN/A
1592124SN/A        // Mark the instruction as squashed, and ready to commit so that
1602132SN/A        // it can drain out of the pipeline.
1612022SN/A        (*squashIt)->setSquashed();
1622124SN/A
1632124SN/A        (*squashIt)->setCanCommit();
1642124SN/A
1653349Sbinkertn@umich.edu#ifndef FULL_SYSTEM
1662124SN/A        if (squashIt == cpu->instList.begin()) {
1672124SN/A            DPRINTF(ROB, "ROB: Reached head of instruction list while "
1682124SN/A                    "squashing.\n");
1693953Sstever@eecs.umich.edu
1702124SN/A            squashIt = cpu->instList.end();
1712124SN/A
1722124SN/A            doneSquashing = true;
1732124SN/A
1742124SN/A            return;
1752124SN/A        }
1763953Sstever@eecs.umich.edu#endif
1772124SN/A
1783953Sstever@eecs.umich.edu        // Move the tail iterator to the next instruction.
1792124SN/A        squashIt--;
1803953Sstever@eecs.umich.edu    }
1813953Sstever@eecs.umich.edu
1822124SN/A
1832124SN/A    // Check if ROB is done squashing.
1842124SN/A    if ((*squashIt)->seqNum == squashedSeqNum) {
1853953Sstever@eecs.umich.edu        DPRINTF(ROB, "ROB: Done squashing instructions.\n");
1862124SN/A
1873953Sstever@eecs.umich.edu        squashIt = cpu->instList.end();
1882124SN/A
1893953Sstever@eecs.umich.edu        doneSquashing = true;
1903953Sstever@eecs.umich.edu    }
1912124SN/A}
1922124SN/A
1932124SN/Atemplate<class Impl>
1942124SN/Avoid
1952124SN/AROB<Impl>::squash(InstSeqNum squash_num)
1962124SN/A{
1972124SN/A    DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n");
1982124SN/A    doneSquashing = false;
1992124SN/A
2002124SN/A    squashedSeqNum = squash_num;
2012132SN/A
2022124SN/A    assert(tail != cpu->instList.end());
2032124SN/A
2042124SN/A    squashIt = tail;
2052124SN/A
2062132SN/A    doSquash();
2072124SN/A}
2082124SN/A
2092124SN/Atemplate<class Impl>
2102124SN/Auint64_t
2113953Sstever@eecs.umich.eduROB<Impl>::readHeadPC()
2122124SN/A{
2132124SN/A    assert(numInstsInROB == countInsts());
2142124SN/A
2152124SN/A    DynInst *head_inst = cpu->instList.front();
2162124SN/A
2172124SN/A    return head_inst->readPC();
2182124SN/A}
2192124SN/A
2202124SN/Atemplate<class Impl>
2212124SN/Auint64_t
2222124SN/AROB<Impl>::readHeadNextPC()
2232132SN/A{
2242124SN/A    assert(numInstsInROB == countInsts());
2252124SN/A
2262124SN/A    DynInst *head_inst = cpu->instList.front();
2272239SN/A
2282132SN/A    return head_inst->readNextPC();
2292239SN/A}
2302239SN/A
2312239SN/Atemplate<class Impl>
2322239SN/AInstSeqNum
2332239SN/AROB<Impl>::readHeadSeqNum()
2342239SN/A{
2352239SN/A    // Return the last sequence number that has not been squashed.  Other
2362239SN/A    // stages can use it to squash any instructions younger than the current
2373953Sstever@eecs.umich.edu    // tail.
2382239SN/A    DynInst *head_inst = cpu->instList.front();
2392239SN/A
2402239SN/A    return head_inst->seqNum;
2412239SN/A}
2422239SN/A
2432239SN/Atemplate<class Impl>
2442124SN/Auint64_t
2452124SN/AROB<Impl>::readTailPC()
2462124SN/A{
2472124SN/A    assert(numInstsInROB == countInsts());
2482124SN/A
2492124SN/A    assert(tail != cpu->instList.end());
2502132SN/A
2512124SN/A    return (*tail)->readPC();
2522124SN/A}
2532124SN/A
2542132SN/Atemplate<class Impl>
2552124SN/AInstSeqNum
2562124SN/AROB<Impl>::readTailSeqNum()
2572124SN/A{
2582124SN/A    // Return the last sequence number that has not been squashed.  Other
2592124SN/A    // stages can use it to squash any instructions younger than the current
2602124SN/A    // tail.
2612124SN/A    return (*tail)->seqNum;
2622124SN/A}
2632124SN/A
2642124SN/A#endif // __ROB_IMPL_HH__
2652124SN/A