rob_impl.hh revision 1681
113219Sodanrc@yahoo.com.br#ifndef __CPU_BETA_CPU_ROB_IMPL_HH__
213219Sodanrc@yahoo.com.br#define __CPU_BETA_CPU_ROB_IMPL_HH__
313219Sodanrc@yahoo.com.br
413219Sodanrc@yahoo.com.br#include "cpu/beta_cpu/rob.hh"
513219Sodanrc@yahoo.com.br
613219Sodanrc@yahoo.com.brtemplate <class Impl>
713219Sodanrc@yahoo.com.brROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth)
813219Sodanrc@yahoo.com.br    : numEntries(_numEntries),
913219Sodanrc@yahoo.com.br      squashWidth(_squashWidth),
1013219Sodanrc@yahoo.com.br      numInstsInROB(0),
1113219Sodanrc@yahoo.com.br      squashedSeqNum(0)
1213219Sodanrc@yahoo.com.br{
1313219Sodanrc@yahoo.com.br    doneSquashing = true;
1413219Sodanrc@yahoo.com.br}
1513219Sodanrc@yahoo.com.br
1613219Sodanrc@yahoo.com.brtemplate <class Impl>
1713219Sodanrc@yahoo.com.brvoid
1813219Sodanrc@yahoo.com.brROB<Impl>::setCPU(FullCPU *cpu_ptr)
1913219Sodanrc@yahoo.com.br{
2013219Sodanrc@yahoo.com.br    cpu = cpu_ptr;
2113219Sodanrc@yahoo.com.br
2213219Sodanrc@yahoo.com.br    // Set the tail to the beginning of the CPU instruction list so that
2313219Sodanrc@yahoo.com.br    // upon the first instruction being inserted into the ROB, the tail
2413219Sodanrc@yahoo.com.br    // iterator can simply be incremented.
2513219Sodanrc@yahoo.com.br    tail = cpu->instList.begin();
2613219Sodanrc@yahoo.com.br
2713219Sodanrc@yahoo.com.br    // Set the squash iterator to the end of the instruction list.
2813219Sodanrc@yahoo.com.br    squashIt = cpu->instList.end();
2913219Sodanrc@yahoo.com.br}
3013219Sodanrc@yahoo.com.br
3113219Sodanrc@yahoo.com.brtemplate <class Impl>
3213219Sodanrc@yahoo.com.brint
3313219Sodanrc@yahoo.com.brROB<Impl>::countInsts()
3413219Sodanrc@yahoo.com.br{
3513219Sodanrc@yahoo.com.br    // Start at 1; if the tail matches cpu->instList.begin(), then there is
3613219Sodanrc@yahoo.com.br    // one inst in the ROB.
3713219Sodanrc@yahoo.com.br    int return_val = 1;
3813219Sodanrc@yahoo.com.br
3913219Sodanrc@yahoo.com.br    // There are quite a few special cases.  Do not use this function other
4013219Sodanrc@yahoo.com.br    // than for debugging purposes.
4113219Sodanrc@yahoo.com.br    if (cpu->instList.begin() == cpu->instList.end()) {
4213219Sodanrc@yahoo.com.br        // In this case there are no instructions in the list.  The ROB
4313219Sodanrc@yahoo.com.br        // must be empty.
4413219Sodanrc@yahoo.com.br        return 0;
4513219Sodanrc@yahoo.com.br    } else if (tail == cpu->instList.end()) {
4613219Sodanrc@yahoo.com.br        // In this case, the tail is not yet pointing to anything valid.
4713219Sodanrc@yahoo.com.br        // The ROB must be empty.
4813219Sodanrc@yahoo.com.br        return 0;
4913219Sodanrc@yahoo.com.br    }
5013219Sodanrc@yahoo.com.br
5113219Sodanrc@yahoo.com.br    // Iterate through the ROB from the head to the tail, counting the
5213219Sodanrc@yahoo.com.br    // entries.
5313219Sodanrc@yahoo.com.br    for (InstIt_t i = cpu->instList.begin(); i != tail; ++i)
5413219Sodanrc@yahoo.com.br    {
5513219Sodanrc@yahoo.com.br        assert(i != cpu->instList.end());
5613219Sodanrc@yahoo.com.br        ++return_val;
5713219Sodanrc@yahoo.com.br    }
5813219Sodanrc@yahoo.com.br
5913219Sodanrc@yahoo.com.br    return return_val;
6013219Sodanrc@yahoo.com.br
6113219Sodanrc@yahoo.com.br    // Because the head won't be tracked properly until the ROB gets the
6213219Sodanrc@yahoo.com.br    // first instruction, and any time that the ROB is empty and has not
6313219Sodanrc@yahoo.com.br    // yet gotten the instruction, this function doesn't work.
6413219Sodanrc@yahoo.com.br//    return numInstsInROB;
6513219Sodanrc@yahoo.com.br}
6613219Sodanrc@yahoo.com.br
6713219Sodanrc@yahoo.com.brtemplate <class Impl>
6813219Sodanrc@yahoo.com.brvoid
6913219Sodanrc@yahoo.com.brROB<Impl>::insertInst(DynInstPtr &inst)
7013219Sodanrc@yahoo.com.br{
7113219Sodanrc@yahoo.com.br    // Make sure we have the right number of instructions.
7213219Sodanrc@yahoo.com.br    assert(numInstsInROB == countInsts());
7313219Sodanrc@yahoo.com.br    // Make sure the instruction is valid.
7413219Sodanrc@yahoo.com.br    assert(inst);
7513219Sodanrc@yahoo.com.br
7613219Sodanrc@yahoo.com.br    DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC());
7713219Sodanrc@yahoo.com.br
7813219Sodanrc@yahoo.com.br    // If the ROB is full then exit.
7913219Sodanrc@yahoo.com.br    assert(numInstsInROB != numEntries);
8013219Sodanrc@yahoo.com.br
8113219Sodanrc@yahoo.com.br    ++numInstsInROB;
8213219Sodanrc@yahoo.com.br
8313219Sodanrc@yahoo.com.br    // Increment the tail iterator, moving it one instruction back.
8413219Sodanrc@yahoo.com.br    // There is a special case if the ROB was empty prior to this insertion,
8513219Sodanrc@yahoo.com.br    // in which case the tail will be pointing at instList.end().  If that
8613219Sodanrc@yahoo.com.br    // happens, then reset the tail to the beginning of the list.
8713219Sodanrc@yahoo.com.br    if (tail != cpu->instList.end()) {
8813219Sodanrc@yahoo.com.br        ++tail;
8913219Sodanrc@yahoo.com.br    } else {
9013219Sodanrc@yahoo.com.br        tail = cpu->instList.begin();
9113219Sodanrc@yahoo.com.br    }
9213219Sodanrc@yahoo.com.br
9313219Sodanrc@yahoo.com.br    // Make sure the tail iterator is actually pointing at the instruction
9413219Sodanrc@yahoo.com.br    // added.
9513219Sodanrc@yahoo.com.br    assert((*tail) == inst);
9613219Sodanrc@yahoo.com.br
9713219Sodanrc@yahoo.com.br    DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB);
9813219Sodanrc@yahoo.com.br
9913219Sodanrc@yahoo.com.br}
10013219Sodanrc@yahoo.com.br
10113219Sodanrc@yahoo.com.br// Whatever calls this function needs to ensure that it properly frees up
10213219Sodanrc@yahoo.com.br// registers prior to this function.
10313219Sodanrc@yahoo.com.brtemplate <class Impl>
10413219Sodanrc@yahoo.com.brvoid
10513219Sodanrc@yahoo.com.brROB<Impl>::retireHead()
10613219Sodanrc@yahoo.com.br{
10713219Sodanrc@yahoo.com.br    assert(numInstsInROB == countInsts());
10813219Sodanrc@yahoo.com.br    assert(numInstsInROB > 0);
10913219Sodanrc@yahoo.com.br
11013219Sodanrc@yahoo.com.br    // Get the head ROB instruction.
11113219Sodanrc@yahoo.com.br    DynInstPtr head_inst = cpu->instList.front();
11213219Sodanrc@yahoo.com.br
11313219Sodanrc@yahoo.com.br    // Make certain this can retire.
11413219Sodanrc@yahoo.com.br    assert(head_inst->readyToCommit());
11513219Sodanrc@yahoo.com.br
11613219Sodanrc@yahoo.com.br    DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, "
11713219Sodanrc@yahoo.com.br            "instruction PC %#x, seq num %i\n", head_inst->readPC(),
11813219Sodanrc@yahoo.com.br            head_inst->seqNum);
11913219Sodanrc@yahoo.com.br
12013219Sodanrc@yahoo.com.br    // Keep track of how many instructions are in the ROB.
12113219Sodanrc@yahoo.com.br    --numInstsInROB;
12213219Sodanrc@yahoo.com.br
12313219Sodanrc@yahoo.com.br    // Tell CPU to remove the instruction from the list of instructions.
12413219Sodanrc@yahoo.com.br    // A special case is needed if the instruction being retired is the
12513219Sodanrc@yahoo.com.br    // only instruction in the ROB; otherwise the tail iterator will become
12613219Sodanrc@yahoo.com.br    // invalidated.
12713219Sodanrc@yahoo.com.br    cpu->removeFrontInst(head_inst);
12813219Sodanrc@yahoo.com.br
12913219Sodanrc@yahoo.com.br    if (numInstsInROB == 0) {
13013219Sodanrc@yahoo.com.br        tail = cpu->instList.end();
13113219Sodanrc@yahoo.com.br    }
13213219Sodanrc@yahoo.com.br}
13313219Sodanrc@yahoo.com.br
13413219Sodanrc@yahoo.com.brtemplate <class Impl>
13513219Sodanrc@yahoo.com.brbool
13613219Sodanrc@yahoo.com.brROB<Impl>::isHeadReady()
13713219Sodanrc@yahoo.com.br{
13813219Sodanrc@yahoo.com.br    if (numInstsInROB != 0) {
13913219Sodanrc@yahoo.com.br        return cpu->instList.front()->readyToCommit();
14013219Sodanrc@yahoo.com.br    }
14113219Sodanrc@yahoo.com.br
14213219Sodanrc@yahoo.com.br    return false;
14313219Sodanrc@yahoo.com.br}
14413219Sodanrc@yahoo.com.br
14513219Sodanrc@yahoo.com.brtemplate <class Impl>
14613219Sodanrc@yahoo.com.brunsigned
14713219Sodanrc@yahoo.com.brROB<Impl>::numFreeEntries()
14813219Sodanrc@yahoo.com.br{
14913219Sodanrc@yahoo.com.br    assert(numInstsInROB == countInsts());
15013219Sodanrc@yahoo.com.br
15113219Sodanrc@yahoo.com.br    return numEntries - numInstsInROB;
15213219Sodanrc@yahoo.com.br}
15313219Sodanrc@yahoo.com.br
15413219Sodanrc@yahoo.com.brtemplate <class Impl>
15513219Sodanrc@yahoo.com.brvoid
15613219Sodanrc@yahoo.com.brROB<Impl>::doSquash()
15713219Sodanrc@yahoo.com.br{
15813219Sodanrc@yahoo.com.br    DPRINTF(ROB, "ROB: Squashing instructions.\n");
15913219Sodanrc@yahoo.com.br
16013219Sodanrc@yahoo.com.br    assert(squashIt != cpu->instList.end());
16113219Sodanrc@yahoo.com.br
16213219Sodanrc@yahoo.com.br    for (int numSquashed = 0;
16313219Sodanrc@yahoo.com.br         numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum;
16413219Sodanrc@yahoo.com.br         ++numSquashed)
16513219Sodanrc@yahoo.com.br    {
16613219Sodanrc@yahoo.com.br        // Ensure that the instruction is younger.
16713219Sodanrc@yahoo.com.br        assert((*squashIt)->seqNum > squashedSeqNum);
16813219Sodanrc@yahoo.com.br
16913219Sodanrc@yahoo.com.br        DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n",
17013219Sodanrc@yahoo.com.br                (*squashIt)->readPC(), (*squashIt)->seqNum);
17113219Sodanrc@yahoo.com.br
17213219Sodanrc@yahoo.com.br        // Mark the instruction as squashed, and ready to commit so that
17313219Sodanrc@yahoo.com.br        // it can drain out of the pipeline.
17413219Sodanrc@yahoo.com.br        (*squashIt)->setSquashed();
17513219Sodanrc@yahoo.com.br
17613219Sodanrc@yahoo.com.br        (*squashIt)->setCanCommit();
17713219Sodanrc@yahoo.com.br
17813219Sodanrc@yahoo.com.br        // Special case for when squashing due to a syscall.  It's possible
17913219Sodanrc@yahoo.com.br        // that the squash happened after the head instruction was already
18013219Sodanrc@yahoo.com.br        // committed, meaning that (*squashIt)->seqNum != squashedSeqNum
18113219Sodanrc@yahoo.com.br        // will never be false.  Normally the squash would never be able
18213219Sodanrc@yahoo.com.br        // to go past the head of the ROB; in this case it might, so it
18313219Sodanrc@yahoo.com.br        // must be handled otherwise it will segfault.
18413219Sodanrc@yahoo.com.br#ifndef FULL_SYSTEM
18513219Sodanrc@yahoo.com.br        if (squashIt == cpu->instList.begin()) {
18613219Sodanrc@yahoo.com.br            DPRINTF(ROB, "ROB: Reached head of instruction list while "
18713219Sodanrc@yahoo.com.br                    "squashing.\n");
18813219Sodanrc@yahoo.com.br
18913219Sodanrc@yahoo.com.br            squashIt = cpu->instList.end();
19013219Sodanrc@yahoo.com.br
19113219Sodanrc@yahoo.com.br            doneSquashing = true;
19213219Sodanrc@yahoo.com.br
19313219Sodanrc@yahoo.com.br            return;
19413219Sodanrc@yahoo.com.br        }
19513219Sodanrc@yahoo.com.br#endif
19613219Sodanrc@yahoo.com.br
19713219Sodanrc@yahoo.com.br        // Move the tail iterator to the next instruction.
19813219Sodanrc@yahoo.com.br        squashIt--;
19913219Sodanrc@yahoo.com.br    }
20013219Sodanrc@yahoo.com.br
20113219Sodanrc@yahoo.com.br
20213219Sodanrc@yahoo.com.br    // Check if ROB is done squashing.
20313219Sodanrc@yahoo.com.br    if ((*squashIt)->seqNum == squashedSeqNum) {
20413219Sodanrc@yahoo.com.br        DPRINTF(ROB, "ROB: Done squashing instructions.\n");
20513219Sodanrc@yahoo.com.br
20613219Sodanrc@yahoo.com.br        squashIt = cpu->instList.end();
20713219Sodanrc@yahoo.com.br
20813219Sodanrc@yahoo.com.br        doneSquashing = true;
20913219Sodanrc@yahoo.com.br    }
21013219Sodanrc@yahoo.com.br}
21113219Sodanrc@yahoo.com.br
21213219Sodanrc@yahoo.com.brtemplate <class Impl>
21313219Sodanrc@yahoo.com.brvoid
21413219Sodanrc@yahoo.com.brROB<Impl>::squash(InstSeqNum squash_num)
21513219Sodanrc@yahoo.com.br{
21613219Sodanrc@yahoo.com.br    DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n");
21713219Sodanrc@yahoo.com.br    doneSquashing = false;
21813219Sodanrc@yahoo.com.br
21913219Sodanrc@yahoo.com.br    squashedSeqNum = squash_num;
22013219Sodanrc@yahoo.com.br
22113219Sodanrc@yahoo.com.br    assert(tail != cpu->instList.end());
22213219Sodanrc@yahoo.com.br
22313219Sodanrc@yahoo.com.br    squashIt = tail;
22413219Sodanrc@yahoo.com.br
22513219Sodanrc@yahoo.com.br    doSquash();
22613219Sodanrc@yahoo.com.br}
227
228template <class Impl>
229uint64_t
230ROB<Impl>::readHeadPC()
231{
232    assert(numInstsInROB == countInsts());
233
234    DynInstPtr head_inst = cpu->instList.front();
235
236    return head_inst->readPC();
237}
238
239template <class Impl>
240uint64_t
241ROB<Impl>::readHeadNextPC()
242{
243    assert(numInstsInROB == countInsts());
244
245    DynInstPtr head_inst = cpu->instList.front();
246
247    return head_inst->readNextPC();
248}
249
250template <class Impl>
251InstSeqNum
252ROB<Impl>::readHeadSeqNum()
253{
254    // Return the last sequence number that has not been squashed.  Other
255    // stages can use it to squash any instructions younger than the current
256    // tail.
257    DynInstPtr head_inst = cpu->instList.front();
258
259    return head_inst->seqNum;
260}
261
262template <class Impl>
263uint64_t
264ROB<Impl>::readTailPC()
265{
266    assert(numInstsInROB == countInsts());
267
268    assert(tail != cpu->instList.end());
269
270    return (*tail)->readPC();
271}
272
273template <class Impl>
274InstSeqNum
275ROB<Impl>::readTailSeqNum()
276{
277    // Return the last sequence number that has not been squashed.  Other
278    // stages can use it to squash any instructions younger than the current
279    // tail.
280    return (*tail)->seqNum;
281}
282
283#endif // __CPU_BETA_CPU_ROB_IMPL_HH__
284