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