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