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