rob_impl.hh revision 1062
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()) {
4610459SAndreas.Sandberg@ARM.com        // In this case, the tail is not yet pointing to anything valid.
476214Snate@binkert.org        // The ROB must be empty.
482SN/A        return 0;
492738Sstever@eecs.umich.edu    }
50395SN/A
51237SN/A    // Iterate through the ROB from the head to the tail, counting the
524000Ssaidi@eecs.umich.edu    // entries.
539983Sstever@gmail.com    for (InstIt_t i = cpu->instList.begin(); i != tail; ++i)
542SN/A    {
559048SAli.Saidi@ARM.com        assert(i != cpu->instList.end());
569048SAli.Saidi@ARM.com        ++return_val;
579056SAli.Saidi@ARM.com    }
589048SAli.Saidi@ARM.com
599048SAli.Saidi@ARM.com    return return_val;
609056SAli.Saidi@ARM.com
619048SAli.Saidi@ARM.com    // Because the head won't be tracked properly until the ROB gets the
6210861SCurtis.Dunham@arm.com    // first instruction, and any time that the ROB is empty and has not
639048SAli.Saidi@ARM.com    // yet gotten the instruction, this function doesn't work.
64217SN/A//    return numInstsInROB;
65502SN/A}
66217SN/A
6710459SAndreas.Sandberg@ARM.comtemplate <class Impl>
6810459SAndreas.Sandberg@ARM.comvoid
6910459SAndreas.Sandberg@ARM.comROB<Impl>::insertInst(DynInstPtr &inst)
7010459SAndreas.Sandberg@ARM.com{
7110459SAndreas.Sandberg@ARM.com    // Make sure we have the right number of instructions.
7210459SAndreas.Sandberg@ARM.com    assert(numInstsInROB == countInsts());
7310459SAndreas.Sandberg@ARM.com    // Make sure the instruction is valid.
74217SN/A    assert(inst);
75237SN/A
76502SN/A    DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC());
77217SN/A
7810459SAndreas.Sandberg@ARM.com    // If the ROB is full then exit.
7910459SAndreas.Sandberg@ARM.com    assert(numInstsInROB != numEntries);
8010459SAndreas.Sandberg@ARM.com
8110459SAndreas.Sandberg@ARM.com    ++numInstsInROB;
8210459SAndreas.Sandberg@ARM.com
8310459SAndreas.Sandberg@ARM.com    // Increment the tail iterator, moving it one instruction back.
8410459SAndreas.Sandberg@ARM.com    // There is a special case if the ROB was empty prior to this insertion,
8510459SAndreas.Sandberg@ARM.com    // in which case the tail will be pointing at instList.end().  If that
86217SN/A    // happens, then reset the tail to the beginning of the list.
876820SLisa.Hsu@amd.com    if (tail != cpu->instList.end()) {
886820SLisa.Hsu@amd.com        ++tail;
896820SLisa.Hsu@amd.com    } else {
9010459SAndreas.Sandberg@ARM.com        tail = cpu->instList.begin();
9110459SAndreas.Sandberg@ARM.com    }
9210459SAndreas.Sandberg@ARM.com
9310459SAndreas.Sandberg@ARM.com    // Make sure the tail iterator is actually pointing at the instruction
9410459SAndreas.Sandberg@ARM.com    // added.
9510459SAndreas.Sandberg@ARM.com    assert((*tail) == inst);
9610459SAndreas.Sandberg@ARM.com
9710459SAndreas.Sandberg@ARM.com    DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB);
986820SLisa.Hsu@amd.com
99217SN/A}
1006227Snate@binkert.org
101217SN/A// Whatever calls this function needs to ensure that it properly frees up
102217SN/A// registers prior to this function.
1034841Ssaidi@eecs.umich.edutemplate <class Impl>
1044841Ssaidi@eecs.umich.eduvoid
1054841Ssaidi@eecs.umich.eduROB<Impl>::retireHead()
1064841Ssaidi@eecs.umich.edu{
1077948SAli.Saidi@ARM.com    assert(numInstsInROB == countInsts());
1087948SAli.Saidi@ARM.com    assert(numInstsInROB > 0);
1097948SAli.Saidi@ARM.com
1107948SAli.Saidi@ARM.com    DynInstPtr head_inst;
111237SN/A
1126227Snate@binkert.org    // Get the head ROB instruction.
113217SN/A    head_inst = cpu->instList.front();
1144841Ssaidi@eecs.umich.edu
1154841Ssaidi@eecs.umich.edu    // Make certain this can retire.
1164841Ssaidi@eecs.umich.edu    assert(head_inst->readyToCommit());
1174841Ssaidi@eecs.umich.edu
1187948SAli.Saidi@ARM.com    DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, "
1197948SAli.Saidi@ARM.com            "instruction PC %#x, seq num %i\n", head_inst->readPC(),
1207948SAli.Saidi@ARM.com            head_inst->seqNum);
1217948SAli.Saidi@ARM.com
122237SN/A    // Keep track of how many instructions are in the ROB.
123237SN/A    --numInstsInROB;
1244000Ssaidi@eecs.umich.edu
125237SN/A    // Tell CPU to remove the instruction from the list of instructions.
1268902Sandreas.hansson@arm.com    // A special case is needed if the instruction being retired is the
1278902Sandreas.hansson@arm.com    // only instruction in the ROB; otherwise the tail iterator will become
1288902Sandreas.hansson@arm.com    // invalidated.
1298902Sandreas.hansson@arm.com    if (tail == cpu->instList.begin()) {
1308902Sandreas.hansson@arm.com        cpu->removeFrontInst(head_inst);
1318902Sandreas.hansson@arm.com        tail = cpu->instList.end();
1328902Sandreas.hansson@arm.com    } else {
1338902Sandreas.hansson@arm.com        cpu->removeFrontInst(head_inst);
1348902Sandreas.hansson@arm.com    }
1358902Sandreas.hansson@arm.com}
1368902Sandreas.hansson@arm.com
137237SN/Atemplate <class Impl>
138217SN/Abool
139217SN/AROB<Impl>::isHeadReady()
140217SN/A{
141237SN/A    if (numInstsInROB != 0) {
1425543Ssaidi@eecs.umich.edu        return cpu->instList.front()->readyToCommit();
143217SN/A    }
1445543Ssaidi@eecs.umich.edu
1456820SLisa.Hsu@amd.com    return false;
146217SN/A}
147223SN/A
1485543Ssaidi@eecs.umich.edutemplate <class Impl>
149223SN/Aunsigned
1505543Ssaidi@eecs.umich.eduROB<Impl>::numFreeEntries()
1515543Ssaidi@eecs.umich.edu{
1525543Ssaidi@eecs.umich.edu    assert(numInstsInROB == countInsts());
1535543Ssaidi@eecs.umich.edu
1548902Sandreas.hansson@arm.com    return numEntries - numInstsInROB;
155223SN/A}
156223SN/A
1575543Ssaidi@eecs.umich.edutemplate <class Impl>
158217SN/Avoid
159217SN/AROB<Impl>::doSquash()
1605543Ssaidi@eecs.umich.edu{
161237SN/A    DPRINTF(ROB, "ROB: Squashing instructions.\n");
162237SN/A
16310903Sandreas.sandberg@arm.com    assert(squashIt != cpu->instList.end());
16410903Sandreas.sandberg@arm.com
16510903Sandreas.sandberg@arm.com    for (int numSquashed = 0;
16610903Sandreas.sandberg@arm.com         numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum;
16710903Sandreas.sandberg@arm.com         ++numSquashed)
16810903Sandreas.sandberg@arm.com    {
1695543Ssaidi@eecs.umich.edu        // Ensure that the instruction is younger.
170237SN/A        assert((*squashIt)->seqNum > squashedSeqNum);
1715543Ssaidi@eecs.umich.edu
1725543Ssaidi@eecs.umich.edu        DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n",
1735543Ssaidi@eecs.umich.edu                (*squashIt)->readPC(), (*squashIt)->seqNum);
1745543Ssaidi@eecs.umich.edu
1758902Sandreas.hansson@arm.com        // Mark the instruction as squashed, and ready to commit so that
176237SN/A        // it can drain out of the pipeline.
177217SN/A        (*squashIt)->setSquashed();
1789342SAndreas.Sandberg@arm.com
1792SN/A        (*squashIt)->setCanCommit();
1809342SAndreas.Sandberg@arm.com
1819342SAndreas.Sandberg@arm.com        // Special case for when squashing due to a syscall.  It's possible
1829342SAndreas.Sandberg@arm.com        // that the squash happened after the head instruction was already
1839342SAndreas.Sandberg@arm.com        // committed, meaning that (*squashIt)->seqNum != squashedSeqNum
1849342SAndreas.Sandberg@arm.com        // will never be false.  Normally the squash would never be able
1859342SAndreas.Sandberg@arm.com        // to go past the head of the ROB; in this case it might, so it
1862SN/A        // must be handled otherwise it will segfault.
187395SN/A#ifndef FULL_SYSTEM
1882SN/A        if (squashIt == cpu->instList.begin()) {
1892SN/A            DPRINTF(ROB, "ROB: Reached head of instruction list while "
190510SN/A                    "squashing.\n");
191510SN/A
1922SN/A            squashIt = cpu->instList.end();
1932SN/A
1945739Snate@binkert.org            doneSquashing = true;
1955739Snate@binkert.org
1962SN/A            return;
197265SN/A        }
198512SN/A#endif
1992SN/A
2005739Snate@binkert.org        // Move the tail iterator to the next instruction.
2015739Snate@binkert.org        squashIt--;
202237SN/A    }
2035739Snate@binkert.org
2042SN/A
2052287SN/A    // Check if ROB is done squashing.
2062287SN/A    if ((*squashIt)->seqNum == squashedSeqNum) {
2072287SN/A        DPRINTF(ROB, "ROB: Done squashing instructions.\n");
2082868Sktlim@umich.edu
209395SN/A        squashIt = cpu->instList.end();
2102SN/A
2112SN/A        doneSquashing = true;
2129554Sandreas.hansson@arm.com    }
2139554Sandreas.hansson@arm.com}
2142SN/A
215395SN/Atemplate <class Impl>
216395SN/Avoid
2172SN/AROB<Impl>::squash(InstSeqNum squash_num)
2182SN/A{
2192SN/A    DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n");
220395SN/A    doneSquashing = false;
2212SN/A
222395SN/A    squashedSeqNum = squash_num;
2232SN/A
2242SN/A    assert(tail != cpu->instList.end());
225395SN/A
2262SN/A    squashIt = tail;
227395SN/A
2282SN/A    doSquash();
2292SN/A}
2302SN/A
231395SN/Atemplate <class Impl>
2322SN/Auint64_t
233395SN/AROB<Impl>::readHeadPC()
2342SN/A{
235395SN/A    assert(numInstsInROB == countInsts());
2362SN/A
2372SN/A    DynInstPtr head_inst = cpu->instList.front();
238395SN/A
239395SN/A    return head_inst->readPC();
2402SN/A}
2412SN/A
2422SN/Atemplate <class Impl>
243395SN/Auint64_t
244395SN/AROB<Impl>::readHeadNextPC()
2452SN/A{
2462SN/A    assert(numInstsInROB == countInsts());
2472SN/A
2482SN/A    DynInstPtr head_inst = cpu->instList.front();
2492SN/A
2502SN/A    return head_inst->readNextPC();
251395SN/A}
2522SN/A
2532SN/Atemplate <class Impl>
2542SN/AInstSeqNum
2552SN/AROB<Impl>::readHeadSeqNum()
2562SN/A{
2572SN/A    // Return the last sequence number that has not been squashed.  Other
2582SN/A    // stages can use it to squash any instructions younger than the current
2592SN/A    // tail.
260395SN/A    DynInstPtr head_inst = cpu->instList.front();
261395SN/A
2622738Sstever@eecs.umich.edu    return head_inst->seqNum;
2632SN/A}
2642SN/A
2652SN/Atemplate <class Impl>
2662SN/Auint64_t
2672SN/AROB<Impl>::readTailPC()
268395SN/A{
269395SN/A    assert(numInstsInROB == countInsts());
2702SN/A
271395SN/A    assert(tail != cpu->instList.end());
2722SN/A
273395SN/A    return (*tail)->readPC();
2742SN/A}
275395SN/A
2762738Sstever@eecs.umich.edutemplate <class Impl>
2772SN/AInstSeqNum
2782SN/AROB<Impl>::readTailSeqNum()
2792SN/A{
2802SN/A    // Return the last sequence number that has not been squashed.  Other
281395SN/A    // stages can use it to squash any instructions younger than the current
2822SN/A    // tail.
2832SN/A    return (*tail)->seqNum;
2845543Ssaidi@eecs.umich.edu}
2855543Ssaidi@eecs.umich.edu
286237SN/A#endif // __ROB_IMPL_HH__
2872SN/A