rob_impl.hh revision 1061
12SN/A#ifndef __ROB_IMPL_HH__
21762SN/A#define __ROB_IMPL_HH__
32SN/A
42SN/A#include "cpu/beta_cpu/rob.hh"
52SN/A
62SN/Atemplate <class Impl>
72SN/AROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth)
82SN/A    : numEntries(_numEntries),
92SN/A      squashWidth(_squashWidth),
102SN/A      numInstsInROB(0),
112SN/A      squashedSeqNum(0)
122SN/A{
132SN/A    doneSquashing = true;
142SN/A}
152SN/A
162SN/Atemplate <class Impl>
172SN/Avoid
182SN/AROB<Impl>::setCPU(FullCPU *cpu_ptr)
192SN/A{
202SN/A    cpu = cpu_ptr;
212SN/A
222SN/A    // Set the tail to the beginning of the CPU instruction list so that
232SN/A    // upon the first instruction being inserted into the ROB, the tail
242SN/A    // iterator can simply be incremented.
252SN/A    tail = cpu->instList.begin();
262SN/A
272665Ssaidi@eecs.umich.edu    // Set the squash iterator to the end of the instruction list.
282760Sbinkertn@umich.edu    squashIt = cpu->instList.end();
292760Sbinkertn@umich.edu}
302665Ssaidi@eecs.umich.edu
312SN/Atemplate <class Impl>
322SN/Aint
332SN/AROB<Impl>::countInsts()
342SN/A{
352SN/A    // Start at 1; if the tail matches cpu->instList.begin(), then there is
362SN/A    // one inst in the ROB.
372SN/A    int return_val = 1;
382SN/A
392SN/A    // There are quite a few special cases.  Do not use this function other
402SN/A    // than for debugging purposes.
418229Snate@binkert.org    if (cpu->instList.begin() == cpu->instList.end()) {
422SN/A        // In this case there are no instructions in the list.  The ROB
438229Snate@binkert.org        // must be empty.
444841Ssaidi@eecs.umich.edu        return 0;
452SN/A    } else if (tail == cpu->instList.end()) {
466214Snate@binkert.org        // In this case, the tail is not yet pointing to anything valid.
472SN/A        // The ROB must be empty.
482738Sstever@eecs.umich.edu        return 0;
49395SN/A    }
50237SN/A
514000Ssaidi@eecs.umich.edu    // Iterate through the ROB from the head to the tail, counting the
529983Sstever@gmail.com    // entries.
532SN/A    for (InstIt_t i = cpu->instList.begin(); i != tail; ++i)
549048SAli.Saidi@ARM.com    {
559048SAli.Saidi@ARM.com        assert(i != cpu->instList.end());
569056SAli.Saidi@ARM.com        ++return_val;
579048SAli.Saidi@ARM.com    }
589048SAli.Saidi@ARM.com
599056SAli.Saidi@ARM.com    return return_val;
609048SAli.Saidi@ARM.com
6110338SCurtis.Dunham@arm.com    // Because the head won't be tracked properly until the ROB gets the
629048SAli.Saidi@ARM.com    // first instruction, and any time that the ROB is empty and has not
63217SN/A    // yet gotten the instruction, this function doesn't work.
64502SN/A//    return numInstsInROB;
65217SN/A}
66217SN/A
67237SN/Atemplate <class Impl>
68502SN/Avoid
69217SN/AROB<Impl>::insertInst(DynInstPtr &inst)
70217SN/A{
716820SLisa.Hsu@amd.com    // Make sure we have the right number of instructions.
726820SLisa.Hsu@amd.com    assert(numInstsInROB == countInsts());
736820SLisa.Hsu@amd.com    // Make sure the instruction is valid.
746820SLisa.Hsu@amd.com    assert(inst);
75217SN/A
766227Snate@binkert.org    DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC());
77217SN/A
78217SN/A    // If the ROB is full then exit.
794841Ssaidi@eecs.umich.edu    assert(numInstsInROB != numEntries);
804841Ssaidi@eecs.umich.edu
814841Ssaidi@eecs.umich.edu    ++numInstsInROB;
824841Ssaidi@eecs.umich.edu
837948SAli.Saidi@ARM.com    // Increment the tail iterator, moving it one instruction back.
847948SAli.Saidi@ARM.com    // There is a special case if the ROB was empty prior to this insertion,
857948SAli.Saidi@ARM.com    // in which case the tail will be pointing at instList.end().  If that
867948SAli.Saidi@ARM.com    // happens, then reset the tail to the beginning of the list.
87237SN/A    if (tail != cpu->instList.end()) {
886227Snate@binkert.org        ++tail;
89217SN/A    } else {
904841Ssaidi@eecs.umich.edu        tail = cpu->instList.begin();
914841Ssaidi@eecs.umich.edu    }
924841Ssaidi@eecs.umich.edu
934841Ssaidi@eecs.umich.edu    // Make sure the tail iterator is actually pointing at the instruction
947948SAli.Saidi@ARM.com    // added.
957948SAli.Saidi@ARM.com    assert((*tail) == inst);
967948SAli.Saidi@ARM.com
977948SAli.Saidi@ARM.com    DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB);
98237SN/A
99237SN/A}
1004000Ssaidi@eecs.umich.edu
101237SN/A// Whatever calls this function needs to ensure that it properly frees up
1028902Sandreas.hansson@arm.com// registers prior to this function.
1038902Sandreas.hansson@arm.comtemplate <class Impl>
1048902Sandreas.hansson@arm.comvoid
1058902Sandreas.hansson@arm.comROB<Impl>::retireHead()
1068902Sandreas.hansson@arm.com{
1078902Sandreas.hansson@arm.com    assert(numInstsInROB == countInsts());
1088902Sandreas.hansson@arm.com    assert(numInstsInROB > 0);
1098902Sandreas.hansson@arm.com
1108902Sandreas.hansson@arm.com    DynInstPtr head_inst;
1118902Sandreas.hansson@arm.com
1128902Sandreas.hansson@arm.com    // Get the head ROB instruction.
113237SN/A    head_inst = cpu->instList.front();
114217SN/A
115217SN/A    // Make certain this can retire.
116217SN/A    assert(head_inst->readyToCommit());
117237SN/A
1185543Ssaidi@eecs.umich.edu    DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, "
119217SN/A            "instruction PC %#x, seq num %i\n", head_inst->readPC(),
1205543Ssaidi@eecs.umich.edu            head_inst->seqNum);
1216820SLisa.Hsu@amd.com
122217SN/A    // Keep track of how many instructions are in the ROB.
123223SN/A    --numInstsInROB;
1245543Ssaidi@eecs.umich.edu
125223SN/A    // Tell CPU to remove the instruction from the list of instructions.
1265543Ssaidi@eecs.umich.edu    // A special case is needed if the instruction being retired is the
1275543Ssaidi@eecs.umich.edu    // only instruction in the ROB; otherwise the tail iterator will become
1285543Ssaidi@eecs.umich.edu    // invalidated.
1295543Ssaidi@eecs.umich.edu    if (tail == cpu->instList.begin()) {
1308902Sandreas.hansson@arm.com        cpu->removeFrontInst(head_inst);
131223SN/A        tail = cpu->instList.end();
132223SN/A    } else {
1335543Ssaidi@eecs.umich.edu        cpu->removeFrontInst(head_inst);
134217SN/A    }
135217SN/A}
1365543Ssaidi@eecs.umich.edu
137237SN/Atemplate <class Impl>
138237SN/Abool
1395543Ssaidi@eecs.umich.eduROB<Impl>::isHeadReady()
140237SN/A{
1415543Ssaidi@eecs.umich.edu    if (numInstsInROB != 0) {
1425543Ssaidi@eecs.umich.edu        DynInstPtr head_inst = cpu->instList.front();
1435543Ssaidi@eecs.umich.edu
1445543Ssaidi@eecs.umich.edu        return head_inst->readyToCommit();
1458902Sandreas.hansson@arm.com    }
146237SN/A
147217SN/A    return false;
1489342SAndreas.Sandberg@arm.com}
1492SN/A
1509342SAndreas.Sandberg@arm.comtemplate <class Impl>
1519342SAndreas.Sandberg@arm.comunsigned
1529342SAndreas.Sandberg@arm.comROB<Impl>::numFreeEntries()
1539342SAndreas.Sandberg@arm.com{
1549342SAndreas.Sandberg@arm.com    assert(numInstsInROB == countInsts());
1559342SAndreas.Sandberg@arm.com
1562SN/A    return numEntries - numInstsInROB;
157395SN/A}
1582SN/A
1592SN/Atemplate <class Impl>
160510SN/Avoid
161510SN/AROB<Impl>::doSquash()
1622SN/A{
1632SN/A    DPRINTF(ROB, "ROB: Squashing instructions.\n");
1645739Snate@binkert.org
1655739Snate@binkert.org    assert(squashIt != cpu->instList.end());
1662SN/A
167265SN/A    for (int numSquashed = 0;
168512SN/A         numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum;
1692SN/A         ++numSquashed)
1705739Snate@binkert.org    {
1715739Snate@binkert.org        // Ensure that the instruction is younger.
172237SN/A        assert((*squashIt)->seqNum > squashedSeqNum);
1735739Snate@binkert.org
1742SN/A        DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n",
1752287SN/A                (*squashIt)->readPC(), (*squashIt)->seqNum);
1762287SN/A
1772287SN/A        // Mark the instruction as squashed, and ready to commit so that
1782868Sktlim@umich.edu        // it can drain out of the pipeline.
179395SN/A        (*squashIt)->setSquashed();
1802SN/A
1812SN/A        (*squashIt)->setCanCommit();
1829554Sandreas.hansson@arm.com
1839554Sandreas.hansson@arm.com        // Special case for when squashing due to a syscall.  It's possible
1842SN/A        // that the squash happened after the head instruction was already
185395SN/A        // committed, meaning that (*squashIt)->seqNum != squashedSeqNum
186395SN/A        // will never be false.  Normally the squash would never be able
1872SN/A        // to go past the head of the ROB; in this case it might, so it
1882SN/A        // must be handled otherwise it will segfault.
1892SN/A#ifndef FULL_SYSTEM
190395SN/A        if (squashIt == cpu->instList.begin()) {
1912SN/A            DPRINTF(ROB, "ROB: Reached head of instruction list while "
192395SN/A                    "squashing.\n");
1932SN/A
1942SN/A            squashIt = cpu->instList.end();
195395SN/A
1962SN/A            doneSquashing = true;
197395SN/A
1982SN/A            return;
1992SN/A        }
2002SN/A#endif
201395SN/A
2022SN/A        // Move the tail iterator to the next instruction.
203395SN/A        squashIt--;
2042SN/A    }
205395SN/A
2062SN/A
2072SN/A    // Check if ROB is done squashing.
208395SN/A    if ((*squashIt)->seqNum == squashedSeqNum) {
209395SN/A        DPRINTF(ROB, "ROB: Done squashing instructions.\n");
2102SN/A
2112SN/A        squashIt = cpu->instList.end();
2122SN/A
213395SN/A        doneSquashing = true;
214395SN/A    }
2152SN/A}
2162SN/A
2172SN/Atemplate <class Impl>
2182SN/Avoid
2192SN/AROB<Impl>::squash(InstSeqNum squash_num)
2202SN/A{
221395SN/A    DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n");
2222SN/A    doneSquashing = false;
2232SN/A
2242SN/A    squashedSeqNum = squash_num;
2252SN/A
2262SN/A    assert(tail != cpu->instList.end());
2272SN/A
2282SN/A    squashIt = tail;
2292SN/A
230395SN/A    doSquash();
231395SN/A}
2322738Sstever@eecs.umich.edu
2332SN/Atemplate <class Impl>
2342SN/Auint64_t
2352SN/AROB<Impl>::readHeadPC()
2362SN/A{
2372SN/A    assert(numInstsInROB == countInsts());
238395SN/A
239395SN/A    DynInstPtr head_inst = cpu->instList.front();
2402SN/A
241395SN/A    return head_inst->readPC();
2422SN/A}
243395SN/A
2442SN/Atemplate <class Impl>
245395SN/Auint64_t
2462738Sstever@eecs.umich.eduROB<Impl>::readHeadNextPC()
2472SN/A{
2482SN/A    assert(numInstsInROB == countInsts());
2492SN/A
2502SN/A    DynInstPtr head_inst = cpu->instList.front();
251395SN/A
2522SN/A    return head_inst->readNextPC();
2532SN/A}
2545543Ssaidi@eecs.umich.edu
2555543Ssaidi@eecs.umich.edutemplate <class Impl>
256237SN/AInstSeqNum
2572SN/AROB<Impl>::readHeadSeqNum()
25810453SAndrew.Bardsley@arm.com{
25910453SAndrew.Bardsley@arm.com    // Return the last sequence number that has not been squashed.  Other
26010453SAndrew.Bardsley@arm.com    // stages can use it to squash any instructions younger than the current
26110453SAndrew.Bardsley@arm.com    // tail.
26210453SAndrew.Bardsley@arm.com    DynInstPtr head_inst = cpu->instList.front();
26310453SAndrew.Bardsley@arm.com
26410453SAndrew.Bardsley@arm.com    return head_inst->seqNum;
26510453SAndrew.Bardsley@arm.com}
26610453SAndrew.Bardsley@arm.com
26710453SAndrew.Bardsley@arm.comtemplate <class Impl>
26810453SAndrew.Bardsley@arm.comuint64_t
26910453SAndrew.Bardsley@arm.comROB<Impl>::readTailPC()
270237SN/A{
271237SN/A    assert(numInstsInROB == countInsts());
272237SN/A
273237SN/A    assert(tail != cpu->instList.end());
274237SN/A
275237SN/A    return (*tail)->readPC();
27610453SAndrew.Bardsley@arm.com}
27710453SAndrew.Bardsley@arm.com
278237SN/Atemplate <class Impl>
27910453SAndrew.Bardsley@arm.comInstSeqNum
2809086Sandreas.hansson@arm.comROB<Impl>::readTailSeqNum()
281237SN/A{
282937SN/A    // Return the last sequence number that has not been squashed.  Other
283937SN/A    // stages can use it to squash any instructions younger than the current
284237SN/A    // tail.
285237SN/A    return (*tail)->seqNum;
286237SN/A}
287237SN/A
2884000Ssaidi@eecs.umich.edu#endif // __ROB_IMPL_HH__
289304SN/A