rob_impl.hh revision 1061
11689SN/A#ifndef __ROB_IMPL_HH__ 27598Sminkyu.jeong@arm.com#define __ROB_IMPL_HH__ 37598Sminkyu.jeong@arm.com 47598Sminkyu.jeong@arm.com#include "cpu/beta_cpu/rob.hh" 57598Sminkyu.jeong@arm.com 67598Sminkyu.jeong@arm.comtemplate <class Impl> 77598Sminkyu.jeong@arm.comROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth) 87598Sminkyu.jeong@arm.com : numEntries(_numEntries), 97598Sminkyu.jeong@arm.com squashWidth(_squashWidth), 107598Sminkyu.jeong@arm.com numInstsInROB(0), 117598Sminkyu.jeong@arm.com squashedSeqNum(0) 127598Sminkyu.jeong@arm.com{ 137598Sminkyu.jeong@arm.com doneSquashing = true; 142326SN/A} 151689SN/A 161689SN/Atemplate <class Impl> 171689SN/Avoid 181689SN/AROB<Impl>::setCPU(FullCPU *cpu_ptr) 191689SN/A{ 201689SN/A cpu = cpu_ptr; 211689SN/A 221689SN/A // Set the tail to the beginning of the CPU instruction list so that 231689SN/A // upon the first instruction being inserted into the ROB, the tail 241689SN/A // iterator can simply be incremented. 251689SN/A tail = cpu->instList.begin(); 261689SN/A 271689SN/A // Set the squash iterator to the end of the instruction list. 281689SN/A squashIt = cpu->instList.end(); 291689SN/A} 301689SN/A 311689SN/Atemplate <class Impl> 321689SN/Aint 331689SN/AROB<Impl>::countInsts() 341689SN/A{ 351689SN/A // Start at 1; if the tail matches cpu->instList.begin(), then there is 361689SN/A // one inst in the ROB. 371689SN/A int return_val = 1; 381689SN/A 392665Ssaidi@eecs.umich.edu // There are quite a few special cases. Do not use this function other 402665Ssaidi@eecs.umich.edu // than for debugging purposes. 411689SN/A if (cpu->instList.begin() == cpu->instList.end()) { 421689SN/A // In this case there are no instructions in the list. The ROB 431060SN/A // must be empty. 441060SN/A return 0; 451689SN/A } else if (tail == cpu->instList.end()) { 461060SN/A // In this case, the tail is not yet pointing to anything valid. 471060SN/A // The ROB must be empty. 481060SN/A return 0; 497813Ssteve.reinhardt@amd.com } 506658Snate@binkert.org 512292SN/A // Iterate through the ROB from the head to the tail, counting the 521717SN/A // entries. 535529Snate@binkert.org for (InstIt_t i = cpu->instList.begin(); i != tail; ++i) 541060SN/A { 556221Snate@binkert.org assert(i != cpu->instList.end()); 566221Snate@binkert.org ++return_val; 571681SN/A } 585529Snate@binkert.org 592873Sktlim@umich.edu return return_val; 604329Sktlim@umich.edu 614329Sktlim@umich.edu // Because the head won't be tracked properly until the ROB gets the 624329Sktlim@umich.edu // first instruction, and any time that the ROB is empty and has not 632292SN/A // yet gotten the instruction, this function doesn't work. 642292SN/A// return numInstsInROB; 652292SN/A} 662292SN/A 672820Sktlim@umich.edutemplate <class Impl> 682292SN/Avoid 692820Sktlim@umich.eduROB<Impl>::insertInst(DynInstPtr &inst) 702820Sktlim@umich.edu{ 715529Snate@binkert.org // Make sure we have the right number of instructions. 722307SN/A assert(numInstsInROB == countInsts()); 731060SN/A // Make sure the instruction is valid. 742292SN/A assert(inst); 752292SN/A 762292SN/A DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC()); 771060SN/A 781060SN/A // If the ROB is full then exit. 791060SN/A assert(numInstsInROB != numEntries); 801060SN/A 811060SN/A ++numInstsInROB; 821060SN/A 831681SN/A // Increment the tail iterator, moving it one instruction back. 846221Snate@binkert.org // There is a special case if the ROB was empty prior to this insertion, 856221Snate@binkert.org // in which case the tail will be pointing at instList.end(). If that 866221Snate@binkert.org // happens, then reset the tail to the beginning of the list. 876221Snate@binkert.org if (tail != cpu->instList.end()) { 882292SN/A ++tail; 892292SN/A } else { 902820Sktlim@umich.edu tail = cpu->instList.begin(); 912820Sktlim@umich.edu } 922292SN/A 932292SN/A // Make sure the tail iterator is actually pointing at the instruction 942820Sktlim@umich.edu // added. 952820Sktlim@umich.edu assert((*tail) == inst); 962292SN/A 972292SN/A DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB); 982292SN/A 992292SN/A} 1002292SN/A 1012292SN/A// Whatever calls this function needs to ensure that it properly frees up 1022292SN/A// registers prior to this function. 1032292SN/Atemplate <class Impl> 1041060SN/Avoid 1051060SN/AROB<Impl>::retireHead() 1061681SN/A{ 1071062SN/A assert(numInstsInROB == countInsts()); 1082292SN/A assert(numInstsInROB > 0); 1091062SN/A 1102301SN/A DynInstPtr head_inst; 1112301SN/A 1121062SN/A // Get the head ROB instruction. 1132727Sktlim@umich.edu head_inst = cpu->instList.front(); 1141062SN/A 1151062SN/A // Make certain this can retire. 1161062SN/A assert(head_inst->readyToCommit()); 1171062SN/A 1181062SN/A DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, " 1191062SN/A "instruction PC %#x, seq num %i\n", head_inst->readPC(), 1201062SN/A head_inst->seqNum); 1211062SN/A 1221062SN/A // Keep track of how many instructions are in the ROB. 1231062SN/A --numInstsInROB; 1241062SN/A 1251062SN/A // Tell CPU to remove the instruction from the list of instructions. 1261062SN/A // A special case is needed if the instruction being retired is the 1271062SN/A // only instruction in the ROB; otherwise the tail iterator will become 1281062SN/A // invalidated. 1291062SN/A if (tail == cpu->instList.begin()) { 1301062SN/A cpu->removeFrontInst(head_inst); 1311062SN/A tail = cpu->instList.end(); 1321062SN/A } else { 1331062SN/A cpu->removeFrontInst(head_inst); 1341062SN/A } 1351062SN/A} 1361062SN/A 1371062SN/Atemplate <class Impl> 1381062SN/Abool 1391062SN/AROB<Impl>::isHeadReady() 1401062SN/A{ 1411062SN/A if (numInstsInROB != 0) { 1421062SN/A DynInstPtr head_inst = cpu->instList.front(); 1431062SN/A 1441062SN/A return head_inst->readyToCommit(); 1451062SN/A } 1461062SN/A 1471062SN/A return false; 1481062SN/A} 1491062SN/A 1501062SN/Atemplate <class Impl> 1511062SN/Aunsigned 1521062SN/AROB<Impl>::numFreeEntries() 1531062SN/A{ 1541062SN/A assert(numInstsInROB == countInsts()); 1552292SN/A 1562292SN/A return numEntries - numInstsInROB; 1572292SN/A} 1582292SN/A 1591062SN/Atemplate <class Impl> 1601062SN/Avoid 1611062SN/AROB<Impl>::doSquash() 1621062SN/A{ 1631062SN/A DPRINTF(ROB, "ROB: Squashing instructions.\n"); 1641062SN/A 1651062SN/A assert(squashIt != cpu->instList.end()); 1662292SN/A 1672292SN/A for (int numSquashed = 0; 1682292SN/A numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum; 1692292SN/A ++numSquashed) 1702292SN/A { 1712292SN/A // Ensure that the instruction is younger. 1722292SN/A assert((*squashIt)->seqNum > squashedSeqNum); 1732292SN/A 1742292SN/A DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n", 1752292SN/A (*squashIt)->readPC(), (*squashIt)->seqNum); 1762301SN/A 1772727Sktlim@umich.edu // Mark the instruction as squashed, and ready to commit so that 1782353SN/A // it can drain out of the pipeline. 1792727Sktlim@umich.edu (*squashIt)->setSquashed(); 1802727Sktlim@umich.edu 1812727Sktlim@umich.edu (*squashIt)->setCanCommit(); 1826221Snate@binkert.org 1832353SN/A // Special case for when squashing due to a syscall. It's possible 1842727Sktlim@umich.edu // that the squash happened after the head instruction was already 1852727Sktlim@umich.edu // committed, meaning that (*squashIt)->seqNum != squashedSeqNum 1862727Sktlim@umich.edu // will never be false. Normally the squash would never be able 1872727Sktlim@umich.edu // to go past the head of the ROB; in this case it might, so it 1882353SN/A // must be handled otherwise it will segfault. 1892727Sktlim@umich.edu#ifndef FULL_SYSTEM 1902727Sktlim@umich.edu if (squashIt == cpu->instList.begin()) { 1912727Sktlim@umich.edu DPRINTF(ROB, "ROB: Reached head of instruction list while " 1926221Snate@binkert.org "squashing.\n"); 1932301SN/A 1942301SN/A squashIt = cpu->instList.end(); 1952727Sktlim@umich.edu 1962301SN/A doneSquashing = true; 1972727Sktlim@umich.edu 1986221Snate@binkert.org return; 1992301SN/A } 2002301SN/A#endif 2012727Sktlim@umich.edu 2022301SN/A // Move the tail iterator to the next instruction. 2032727Sktlim@umich.edu squashIt--; 2046221Snate@binkert.org } 2052301SN/A 2062301SN/A 2072727Sktlim@umich.edu // Check if ROB is done squashing. 2082301SN/A if ((*squashIt)->seqNum == squashedSeqNum) { 2092727Sktlim@umich.edu DPRINTF(ROB, "ROB: Done squashing instructions.\n"); 2106221Snate@binkert.org 2112301SN/A squashIt = cpu->instList.end(); 2122301SN/A 2132727Sktlim@umich.edu doneSquashing = true; 2142301SN/A } 2152301SN/A} 2162301SN/A 2172301SN/Atemplate <class Impl> 2182727Sktlim@umich.eduvoid 2192727Sktlim@umich.eduROB<Impl>::squash(InstSeqNum squash_num) 2202727Sktlim@umich.edu{ 2212727Sktlim@umich.edu DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n"); 2222727Sktlim@umich.edu doneSquashing = false; 2232727Sktlim@umich.edu 2242727Sktlim@umich.edu squashedSeqNum = squash_num; 2252727Sktlim@umich.edu 2262727Sktlim@umich.edu assert(tail != cpu->instList.end()); 2272301SN/A 2282301SN/A squashIt = tail; 2296221Snate@binkert.org 2302301SN/A doSquash(); 2312301SN/A} 2322727Sktlim@umich.edu 2332301SN/Atemplate <class Impl> 2342326SN/Auint64_t 2356221Snate@binkert.orgROB<Impl>::readHeadPC() 2362301SN/A{ 2372301SN/A assert(numInstsInROB == countInsts()); 2382727Sktlim@umich.edu 2392301SN/A DynInstPtr head_inst = cpu->instList.front(); 2402326SN/A 2416221Snate@binkert.org return head_inst->readPC(); 2422301SN/A} 2432301SN/A 2442727Sktlim@umich.edutemplate <class Impl> 2452301SN/Auint64_t 2462326SN/AROB<Impl>::readHeadNextPC() 2476221Snate@binkert.org{ 2482301SN/A assert(numInstsInROB == countInsts()); 2492301SN/A 2502727Sktlim@umich.edu DynInstPtr head_inst = cpu->instList.front(); 2512301SN/A 2522326SN/A return head_inst->readNextPC(); 2536221Snate@binkert.org} 2542301SN/A 2552301SN/Atemplate <class Impl> 2562727Sktlim@umich.eduInstSeqNum 2572301SN/AROB<Impl>::readHeadSeqNum() 2582326SN/A{ 2592301SN/A // Return the last sequence number that has not been squashed. Other 2602301SN/A // stages can use it to squash any instructions younger than the current 2612727Sktlim@umich.edu // tail. 2622301SN/A DynInstPtr head_inst = cpu->instList.front(); 2632326SN/A 2642301SN/A return head_inst->seqNum; 2652326SN/A} 2662301SN/A 2672301SN/Atemplate <class Impl> 2682727Sktlim@umich.eduuint64_t 2692301SN/AROB<Impl>::readTailPC() 2702326SN/A{ 2712301SN/A assert(numInstsInROB == countInsts()); 2722326SN/A 2732301SN/A assert(tail != cpu->instList.end()); 2742301SN/A 2752727Sktlim@umich.edu return (*tail)->readPC(); 2762326SN/A} 2771062SN/A 2781062SN/Atemplate <class Impl> 2791681SN/AInstSeqNum 2801060SN/AROB<Impl>::readTailSeqNum() 2812292SN/A{ 2821060SN/A // Return the last sequence number that has not been squashed. Other 2836221Snate@binkert.org // stages can use it to squash any instructions younger than the current 2842292SN/A // tail. 2852292SN/A return (*tail)->seqNum; 2862292SN/A} 2872292SN/A 2882292SN/A#endif // __ROB_IMPL_HH__ 2892292SN/A