rob_impl.hh revision 1060
11689SN/A#ifndef __ROB_IMPL_HH__
29444SAndreas.Sandberg@ARM.com#define __ROB_IMPL_HH__
39444SAndreas.Sandberg@ARM.com
49444SAndreas.Sandberg@ARM.com#include "cpu/beta_cpu/rob.hh"
59444SAndreas.Sandberg@ARM.com
69444SAndreas.Sandberg@ARM.comtemplate<class Impl>
79444SAndreas.Sandberg@ARM.comROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth)
89444SAndreas.Sandberg@ARM.com    : numEntries(_numEntries),
99444SAndreas.Sandberg@ARM.com      squashWidth(_squashWidth),
109444SAndreas.Sandberg@ARM.com      numInstsInROB(0),
119444SAndreas.Sandberg@ARM.com      squashedSeqNum(0)
129444SAndreas.Sandberg@ARM.com{
139444SAndreas.Sandberg@ARM.com    doneSquashing = true;
142329SN/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    tail = cpu->instList.begin();
231689SN/A
241689SN/A    squashIt = cpu->instList.end();
251689SN/A}
261689SN/A
271689SN/Atemplate<class Impl>
281689SN/Aint
291689SN/AROB<Impl>::countInsts()
301689SN/A{
311689SN/A/*
321689SN/A    int return_val = 0;
331689SN/A
341689SN/A    // Iterate through the ROB from the head to the tail, counting the
351689SN/A    // entries.
361689SN/A    for (InstIt i = cpu->instList.begin(); i != tail; i++)
371689SN/A    {
381689SN/A        assert(i != cpu->instList.end());
392665Ssaidi@eecs.umich.edu        return_val++;
402665Ssaidi@eecs.umich.edu    }
412831Sksewell@umich.edu
421689SN/A    return return_val;
431689SN/A*/
449944Smatt.horsnell@ARM.com    // Because the head won't be tracked properly until the ROB gets the
459944Smatt.horsnell@ARM.com    // first instruction, and any time that the ROB is empty and has not
469944Smatt.horsnell@ARM.com    // yet gotten the instruction, this function doesn't work.
476221Snate@binkert.org    return numInstsInROB;
486221Snate@binkert.org}
491717SN/A
508232Snate@binkert.orgtemplate<class Impl>
518232Snate@binkert.orgvoid
529954SFaissal.Sleiman@arm.comROB<Impl>::insertInst(DynInst *inst)
531060SN/A{
546221Snate@binkert.org    // Make sure we have the right number of instructions.
552292SN/A    assert(numInstsInROB == countInsts());
561061SN/A    // Make sure the instruction is valid.
579954SFaissal.Sleiman@arm.com    assert(inst);
584329Sktlim@umich.edu
599954SFaissal.Sleiman@arm.com    DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC());
609954SFaissal.Sleiman@arm.com
611060SN/A    // If the ROB is full then exit.
629954SFaissal.Sleiman@arm.com    assert(numInstsInROB != numEntries);
631060SN/A
649954SFaissal.Sleiman@arm.com    ++numInstsInROB;
652292SN/A
662292SN/A    // Increment the tail iterator, moving it one instruction back.
672292SN/A    // There is a special case if the ROB was empty prior to this insertion,
682292SN/A    // in which case the tail will be pointing at instList.end().  If that
692292SN/A    // happens, then reset the tail to the beginning of the list.
702292SN/A    if (tail != cpu->instList.end()) {
712292SN/A        tail++;
722292SN/A    } else {
732292SN/A        tail = cpu->instList.begin();
742292SN/A    }
756221Snate@binkert.org
766221Snate@binkert.org    // Make sure the tail iterator is actually pointing at the instruction
772292SN/A    // added.
782292SN/A    assert((*tail) == inst);
792292SN/A
802292SN/A    DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB);
814329Sktlim@umich.edu
822292SN/A}
832292SN/A
842292SN/A// Whatever calls this function needs to ensure that it properly frees up
852292SN/A// registers prior to this function.
862292SN/Atemplate<class Impl>
876221Snate@binkert.orgvoid
886221Snate@binkert.orgROB<Impl>::retireHead()
892292SN/A{
902292SN/A    assert(numInstsInROB == countInsts());
912292SN/A
922292SN/A    DynInst *head_inst;
934329Sktlim@umich.edu
942292SN/A    // Get the head ROB instruction.
959954SFaissal.Sleiman@arm.com    head_inst = cpu->instList.front();
962292SN/A
972292SN/A    // Make certain this can retire.
986221Snate@binkert.org    assert(head_inst->readyToCommit());
996221Snate@binkert.org
1002292SN/A    DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, "
1012292SN/A            "instruction PC %#x, seq num %i\n", head_inst->readPC(),
1022292SN/A            head_inst->seqNum);
1032292SN/A
1042292SN/A    // Keep track of how many instructions are in the ROB.
1051060SN/A    --numInstsInROB;
1069444SAndreas.Sandberg@ARM.com
1079444SAndreas.Sandberg@ARM.com    // Tell CPU to remove the instruction from the list of instructions.
1089444SAndreas.Sandberg@ARM.com    // A special case is needed if the instruction being retired is the
1099444SAndreas.Sandberg@ARM.com    // only instruction in the ROB; otherwise the tail iterator will become
1109444SAndreas.Sandberg@ARM.com    // invalidated.
1119444SAndreas.Sandberg@ARM.com    if (tail == cpu->instList.begin()) {
1129444SAndreas.Sandberg@ARM.com        cpu->removeFrontInst(head_inst);
1139444SAndreas.Sandberg@ARM.com        tail = cpu->instList.end();
1149444SAndreas.Sandberg@ARM.com    } else {
1159444SAndreas.Sandberg@ARM.com        cpu->removeFrontInst(head_inst);
1166221Snate@binkert.org    }
1179444SAndreas.Sandberg@ARM.com}
1182292SN/A
1199444SAndreas.Sandberg@ARM.comtemplate<class Impl>
1201060SN/Abool
1212292SN/AROB<Impl>::isHeadReady()
1222292SN/A{
1232292SN/A    if (numInstsInROB != 0) {
1242292SN/A        DynInst *head_inst = cpu->instList.front();
1252292SN/A
1262292SN/A        return head_inst->readyToCommit();
1272292SN/A    }
1284329Sktlim@umich.edu
1294329Sktlim@umich.edu    return false;
1304329Sktlim@umich.edu}
1314329Sktlim@umich.edu
1324329Sktlim@umich.edutemplate<class Impl>
1334329Sktlim@umich.eduunsigned
1344329Sktlim@umich.eduROB<Impl>::numFreeEntries()
1352292SN/A{
1366221Snate@binkert.org    assert(numInstsInROB == countInsts());
1372292SN/A
1382292SN/A    return numEntries - numInstsInROB;
1392292SN/A}
1402292SN/A
1412292SN/Atemplate<class Impl>
1422307SN/Avoid
1432307SN/AROB<Impl>::doSquash()
1449444SAndreas.Sandberg@ARM.com{
1452307SN/A    DPRINTF(ROB, "ROB: Squashing instructions.\n");
1469444SAndreas.Sandberg@ARM.com
1479444SAndreas.Sandberg@ARM.com    assert(squashIt != cpu->instList.end());
1489444SAndreas.Sandberg@ARM.com
1492307SN/A    for (int numSquashed = 0;
1502307SN/A         numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum;
1512307SN/A         ++numSquashed)
1522307SN/A    {
1532307SN/A        // Ensure that the instruction is younger.
1542307SN/A        assert((*squashIt)->seqNum > squashedSeqNum);
1559444SAndreas.Sandberg@ARM.com
1562307SN/A        DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n",
1572292SN/A                (*squashIt)->readPC(), (*squashIt)->seqNum);
1582292SN/A
1592292SN/A        // Mark the instruction as squashed, and ready to commit so that
1602292SN/A        // it can drain out of the pipeline.
1612292SN/A        (*squashIt)->setSquashed();
1622292SN/A
1633867Sbinkertn@umich.edu        (*squashIt)->setCanCommit();
1642292SN/A
1656221Snate@binkert.org#ifndef FULL_SYSTEM
1666221Snate@binkert.org        if (squashIt == cpu->instList.begin()) {
1672292SN/A            DPRINTF(ROB, "ROB: Reached head of instruction list while "
1683867Sbinkertn@umich.edu                    "squashing.\n");
1696221Snate@binkert.org
1703867Sbinkertn@umich.edu            squashIt = cpu->instList.end();
1712292SN/A
1723867Sbinkertn@umich.edu            doneSquashing = true;
1732292SN/A
1743867Sbinkertn@umich.edu            return;
1752292SN/A        }
1762292SN/A#endif
1772292SN/A
1782292SN/A        // Move the tail iterator to the next instruction.
1792292SN/A        squashIt--;
1802292SN/A    }
1812292SN/A
1826221Snate@binkert.org
1832292SN/A    // Check if ROB is done squashing.
1842292SN/A    if ((*squashIt)->seqNum == squashedSeqNum) {
1852292SN/A        DPRINTF(ROB, "ROB: Done squashing instructions.\n");
1862292SN/A
1872292SN/A        squashIt = cpu->instList.end();
1882292SN/A
1891060SN/A        doneSquashing = true;
1901060SN/A    }
1911061SN/A}
1921060SN/A
1931060SN/Atemplate<class Impl>
1941060SN/Avoid
1956221Snate@binkert.orgROB<Impl>::squash(InstSeqNum squash_num)
1961061SN/A{
1976221Snate@binkert.org    DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n");
1986221Snate@binkert.org    doneSquashing = false;
1991060SN/A
2002292SN/A    squashedSeqNum = squash_num;
2012292SN/A
2021060SN/A    assert(tail != cpu->instList.end());
2032292SN/A
2042292SN/A    squashIt = tail;
2056221Snate@binkert.org
2062292SN/A    doSquash();
2072292SN/A}
2081060SN/A
2091060SN/Atemplate<class Impl>
2101061SN/Auint64_t
2111060SN/AROB<Impl>::readHeadPC()
2121061SN/A{
2131060SN/A    assert(numInstsInROB == countInsts());
2141060SN/A
2151060SN/A    DynInst *head_inst = cpu->instList.front();
2167897Shestness@cs.utexas.edu
2177897Shestness@cs.utexas.edu    return head_inst->readPC();
2187720Sgblack@eecs.umich.edu}
2191060SN/A
2201060SN/Atemplate<class Impl>
2211060SN/Auint64_t
2226221Snate@binkert.orgROB<Impl>::readHeadNextPC()
2231060SN/A{
2242292SN/A    assert(numInstsInROB == countInsts());
2252292SN/A
2262292SN/A    DynInst *head_inst = cpu->instList.front();
2272292SN/A
2282292SN/A    return head_inst->readNextPC();
2292292SN/A}
2301060SN/A
2311060SN/Atemplate<class Impl>
2322292SN/AInstSeqNum
2332292SN/AROB<Impl>::readHeadSeqNum()
2342292SN/A{
2352292SN/A    // Return the last sequence number that has not been squashed.  Other
2362292SN/A    // stages can use it to squash any instructions younger than the current
2372292SN/A    // tail.
2382292SN/A    DynInst *head_inst = cpu->instList.front();
2392292SN/A
2402292SN/A    return head_inst->seqNum;
2412292SN/A}
2421060SN/A
2431060SN/Atemplate<class Impl>
2442292SN/Auint64_t
2451060SN/AROB<Impl>::readTailPC()
2461060SN/A{
2472292SN/A    assert(numInstsInROB == countInsts());
2482292SN/A
2496221Snate@binkert.org    assert(tail != cpu->instList.end());
2502292SN/A
2517897Shestness@cs.utexas.edu    return (*tail)->readPC();
2527897Shestness@cs.utexas.edu}
2531061SN/A
2541060SN/Atemplate<class Impl>
2551060SN/AInstSeqNum
2562292SN/AROB<Impl>::readTailSeqNum()
2571060SN/A{
2582292SN/A    // Return the last sequence number that has not been squashed.  Other
2591858SN/A    // stages can use it to squash any instructions younger than the current
2601060SN/A    // tail.
2611060SN/A    return (*tail)->seqNum;
2622292SN/A}
2637720Sgblack@eecs.umich.edu
2641060SN/A#endif // __ROB_IMPL_HH__
2651060SN/A