rob_impl.hh revision 1681
14120Sgblack@eecs.umich.edu#ifndef __CPU_BETA_CPU_ROB_IMPL_HH__ 24120Sgblack@eecs.umich.edu#define __CPU_BETA_CPU_ROB_IMPL_HH__ 34120Sgblack@eecs.umich.edu 44120Sgblack@eecs.umich.edu#include "cpu/beta_cpu/rob.hh" 57087Snate@binkert.org 67087Snate@binkert.orgtemplate <class Impl> 77087Snate@binkert.orgROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth) 87087Snate@binkert.org : numEntries(_numEntries), 97087Snate@binkert.org squashWidth(_squashWidth), 107087Snate@binkert.org numInstsInROB(0), 117087Snate@binkert.org squashedSeqNum(0) 127087Snate@binkert.org{ 134120Sgblack@eecs.umich.edu doneSquashing = true; 147087Snate@binkert.org} 157087Snate@binkert.org 167087Snate@binkert.orgtemplate <class Impl> 177087Snate@binkert.orgvoid 187087Snate@binkert.orgROB<Impl>::setCPU(FullCPU *cpu_ptr) 197087Snate@binkert.org{ 207087Snate@binkert.org cpu = cpu_ptr; 217087Snate@binkert.org 224120Sgblack@eecs.umich.edu // Set the tail to the beginning of the CPU instruction list so that 237087Snate@binkert.org // upon the first instruction being inserted into the ROB, the tail 244120Sgblack@eecs.umich.edu // iterator can simply be incremented. 254120Sgblack@eecs.umich.edu tail = cpu->instList.begin(); 264120Sgblack@eecs.umich.edu 274120Sgblack@eecs.umich.edu // Set the squash iterator to the end of the instruction list. 284120Sgblack@eecs.umich.edu squashIt = cpu->instList.end(); 294120Sgblack@eecs.umich.edu} 304120Sgblack@eecs.umich.edu 314120Sgblack@eecs.umich.edutemplate <class Impl> 324120Sgblack@eecs.umich.eduint 334120Sgblack@eecs.umich.eduROB<Impl>::countInsts() 344120Sgblack@eecs.umich.edu{ 354120Sgblack@eecs.umich.edu // Start at 1; if the tail matches cpu->instList.begin(), then there is 364120Sgblack@eecs.umich.edu // one inst in the ROB. 374120Sgblack@eecs.umich.edu int return_val = 1; 384120Sgblack@eecs.umich.edu 394120Sgblack@eecs.umich.edu // There are quite a few special cases. Do not use this function other 404120Sgblack@eecs.umich.edu // than for debugging purposes. 414120Sgblack@eecs.umich.edu if (cpu->instList.begin() == cpu->instList.end()) { 424120Sgblack@eecs.umich.edu // In this case there are no instructions in the list. The ROB 435857Sgblack@eecs.umich.edu // must be empty. 444139Sgblack@eecs.umich.edu return 0; 454135Sgblack@eecs.umich.edu } else if (tail == cpu->instList.end()) { 466023Snate@binkert.org // In this case, the tail is not yet pointing to anything valid. 474120Sgblack@eecs.umich.edu // The ROB must be empty. 485909Sgblack@eecs.umich.edu return 0; 495909Sgblack@eecs.umich.edu } 504120Sgblack@eecs.umich.edu 514120Sgblack@eecs.umich.edu // Iterate through the ROB from the head to the tail, counting the 525114Sgblack@eecs.umich.edu // entries. 535114Sgblack@eecs.umich.edu for (InstIt_t i = cpu->instList.begin(); i != tail; ++i) 544135Sgblack@eecs.umich.edu { 554365Sgblack@eecs.umich.edu assert(i != cpu->instList.end()); 565114Sgblack@eecs.umich.edu ++return_val; 575114Sgblack@eecs.umich.edu } 585851Sgblack@eecs.umich.edu 595139Sgblack@eecs.umich.edu return return_val; 605114Sgblack@eecs.umich.edu 615139Sgblack@eecs.umich.edu // Because the head won't be tracked properly until the ROB gets the 626009Snate@binkert.org // first instruction, and any time that the ROB is empty and has not 636009Snate@binkert.org // yet gotten the instruction, this function doesn't work. 646009Snate@binkert.org// return numInstsInROB; 655114Sgblack@eecs.umich.edu} 665114Sgblack@eecs.umich.edu 675114Sgblack@eecs.umich.edutemplate <class Impl> 684729Sgblack@eecs.umich.eduvoid 694365Sgblack@eecs.umich.eduROB<Impl>::insertInst(DynInstPtr &inst) 705114Sgblack@eecs.umich.edu{ 714365Sgblack@eecs.umich.edu // Make sure we have the right number of instructions. 724365Sgblack@eecs.umich.edu assert(numInstsInROB == countInsts()); 735114Sgblack@eecs.umich.edu // Make sure the instruction is valid. 745114Sgblack@eecs.umich.edu assert(inst); 755114Sgblack@eecs.umich.edu 765114Sgblack@eecs.umich.edu DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC()); 775114Sgblack@eecs.umich.edu 785114Sgblack@eecs.umich.edu // If the ROB is full then exit. 795114Sgblack@eecs.umich.edu assert(numInstsInROB != numEntries); 805114Sgblack@eecs.umich.edu 815114Sgblack@eecs.umich.edu ++numInstsInROB; 825684Sgblack@eecs.umich.edu 835858Sgblack@eecs.umich.edu // Increment the tail iterator, moving it one instruction back. 845684Sgblack@eecs.umich.edu // There is a special case if the ROB was empty prior to this insertion, 855858Sgblack@eecs.umich.edu // in which case the tail will be pointing at instList.end(). If that 865684Sgblack@eecs.umich.edu // happens, then reset the tail to the beginning of the list. 875858Sgblack@eecs.umich.edu if (tail != cpu->instList.end()) { 885858Sgblack@eecs.umich.edu ++tail; 895858Sgblack@eecs.umich.edu } else { 905909Sgblack@eecs.umich.edu tail = cpu->instList.begin(); 915909Sgblack@eecs.umich.edu } 925858Sgblack@eecs.umich.edu 935114Sgblack@eecs.umich.edu // Make sure the tail iterator is actually pointing at the instruction 945114Sgblack@eecs.umich.edu // added. 955114Sgblack@eecs.umich.edu assert((*tail) == inst); 965114Sgblack@eecs.umich.edu 975114Sgblack@eecs.umich.edu DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB); 985114Sgblack@eecs.umich.edu 995114Sgblack@eecs.umich.edu} 1005139Sgblack@eecs.umich.edu 1016009Snate@binkert.org// Whatever calls this function needs to ensure that it properly frees up 1026009Snate@binkert.org// registers prior to this function. 1035114Sgblack@eecs.umich.edutemplate <class Impl> 1045114Sgblack@eecs.umich.eduvoid 1055114Sgblack@eecs.umich.eduROB<Impl>::retireHead() 1065114Sgblack@eecs.umich.edu{ 1075114Sgblack@eecs.umich.edu assert(numInstsInROB == countInsts()); 1085114Sgblack@eecs.umich.edu assert(numInstsInROB > 0); 1095114Sgblack@eecs.umich.edu 1105114Sgblack@eecs.umich.edu // Get the head ROB instruction. 1115139Sgblack@eecs.umich.edu DynInstPtr head_inst = cpu->instList.front(); 1126009Snate@binkert.org 1136009Snate@binkert.org // Make certain this can retire. 1145114Sgblack@eecs.umich.edu assert(head_inst->readyToCommit()); 1155114Sgblack@eecs.umich.edu 1165114Sgblack@eecs.umich.edu DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, " 1175124Sgblack@eecs.umich.edu "instruction PC %#x, seq num %i\n", head_inst->readPC(), 1185114Sgblack@eecs.umich.edu head_inst->seqNum); 1195114Sgblack@eecs.umich.edu 1205114Sgblack@eecs.umich.edu // Keep track of how many instructions are in the ROB. 1215114Sgblack@eecs.umich.edu --numInstsInROB; 1225114Sgblack@eecs.umich.edu 1235114Sgblack@eecs.umich.edu // Tell CPU to remove the instruction from the list of instructions. 1245114Sgblack@eecs.umich.edu // A special case is needed if the instruction being retired is the 1255139Sgblack@eecs.umich.edu // only instruction in the ROB; otherwise the tail iterator will become 1266009Snate@binkert.org // invalidated. 1276009Snate@binkert.org cpu->removeFrontInst(head_inst); 1285114Sgblack@eecs.umich.edu 1295114Sgblack@eecs.umich.edu if (numInstsInROB == 0) { 1305114Sgblack@eecs.umich.edu tail = cpu->instList.end(); 1315124Sgblack@eecs.umich.edu } 1325114Sgblack@eecs.umich.edu} 1335114Sgblack@eecs.umich.edu 1345114Sgblack@eecs.umich.edutemplate <class Impl> 1355114Sgblack@eecs.umich.edubool 1365114Sgblack@eecs.umich.eduROB<Impl>::isHeadReady() 1375114Sgblack@eecs.umich.edu{ 1385114Sgblack@eecs.umich.edu if (numInstsInROB != 0) { 1395851Sgblack@eecs.umich.edu return cpu->instList.front()->readyToCommit(); 1406009Snate@binkert.org } 1416009Snate@binkert.org 1425114Sgblack@eecs.umich.edu return false; 1434135Sgblack@eecs.umich.edu} 1444150Sgblack@eecs.umich.edu 1454365Sgblack@eecs.umich.edutemplate <class Impl> 1464365Sgblack@eecs.umich.eduunsigned 1474365Sgblack@eecs.umich.eduROB<Impl>::numFreeEntries() 1484729Sgblack@eecs.umich.edu{ 1494365Sgblack@eecs.umich.edu assert(numInstsInROB == countInsts()); 1504365Sgblack@eecs.umich.edu 1514365Sgblack@eecs.umich.edu return numEntries - numInstsInROB; 1524365Sgblack@eecs.umich.edu} 1534365Sgblack@eecs.umich.edu 1544365Sgblack@eecs.umich.edutemplate <class Impl> 1554365Sgblack@eecs.umich.eduvoid 1564365Sgblack@eecs.umich.eduROB<Impl>::doSquash() 1574365Sgblack@eecs.umich.edu{ 1584365Sgblack@eecs.umich.edu DPRINTF(ROB, "ROB: Squashing instructions.\n"); 1594150Sgblack@eecs.umich.edu 1604150Sgblack@eecs.umich.edu assert(squashIt != cpu->instList.end()); 1614150Sgblack@eecs.umich.edu 1624150Sgblack@eecs.umich.edu for (int numSquashed = 0; 1635114Sgblack@eecs.umich.edu numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum; 1645114Sgblack@eecs.umich.edu ++numSquashed) 1655114Sgblack@eecs.umich.edu { 1665114Sgblack@eecs.umich.edu // Ensure that the instruction is younger. 1675114Sgblack@eecs.umich.edu assert((*squashIt)->seqNum > squashedSeqNum); 1685114Sgblack@eecs.umich.edu 1695114Sgblack@eecs.umich.edu DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n", 1705114Sgblack@eecs.umich.edu (*squashIt)->readPC(), (*squashIt)->seqNum); 1715114Sgblack@eecs.umich.edu 1725114Sgblack@eecs.umich.edu // Mark the instruction as squashed, and ready to commit so that 1735114Sgblack@eecs.umich.edu // it can drain out of the pipeline. 1745114Sgblack@eecs.umich.edu (*squashIt)->setSquashed(); 1755114Sgblack@eecs.umich.edu 1765114Sgblack@eecs.umich.edu (*squashIt)->setCanCommit(); 1775114Sgblack@eecs.umich.edu 1785114Sgblack@eecs.umich.edu // Special case for when squashing due to a syscall. It's possible 1795114Sgblack@eecs.umich.edu // that the squash happened after the head instruction was already 1805114Sgblack@eecs.umich.edu // committed, meaning that (*squashIt)->seqNum != squashedSeqNum 1815114Sgblack@eecs.umich.edu // will never be false. Normally the squash would never be able 1825114Sgblack@eecs.umich.edu // to go past the head of the ROB; in this case it might, so it 1835114Sgblack@eecs.umich.edu // must be handled otherwise it will segfault. 1845114Sgblack@eecs.umich.edu#ifndef FULL_SYSTEM 1855114Sgblack@eecs.umich.edu if (squashIt == cpu->instList.begin()) { 1865114Sgblack@eecs.umich.edu DPRINTF(ROB, "ROB: Reached head of instruction list while " 1875114Sgblack@eecs.umich.edu "squashing.\n"); 1885114Sgblack@eecs.umich.edu 1895114Sgblack@eecs.umich.edu squashIt = cpu->instList.end(); 1905114Sgblack@eecs.umich.edu 1915114Sgblack@eecs.umich.edu doneSquashing = true; 1925114Sgblack@eecs.umich.edu 1935114Sgblack@eecs.umich.edu return; 1945114Sgblack@eecs.umich.edu } 1955114Sgblack@eecs.umich.edu#endif 1965114Sgblack@eecs.umich.edu 1975114Sgblack@eecs.umich.edu // Move the tail iterator to the next instruction. 1985114Sgblack@eecs.umich.edu squashIt--; 1995851Sgblack@eecs.umich.edu } 2005114Sgblack@eecs.umich.edu 2015114Sgblack@eecs.umich.edu 2025114Sgblack@eecs.umich.edu // Check if ROB is done squashing. 2035114Sgblack@eecs.umich.edu if ((*squashIt)->seqNum == squashedSeqNum) { 2045114Sgblack@eecs.umich.edu DPRINTF(ROB, "ROB: Done squashing instructions.\n"); 2055114Sgblack@eecs.umich.edu 2065114Sgblack@eecs.umich.edu squashIt = cpu->instList.end(); 2075851Sgblack@eecs.umich.edu 2085114Sgblack@eecs.umich.edu doneSquashing = true; 2095114Sgblack@eecs.umich.edu } 2105114Sgblack@eecs.umich.edu} 2115114Sgblack@eecs.umich.edu 2125114Sgblack@eecs.umich.edutemplate <class Impl> 2135114Sgblack@eecs.umich.eduvoid 2145655Sgblack@eecs.umich.eduROB<Impl>::squash(InstSeqNum squash_num) 2155851Sgblack@eecs.umich.edu{ 2165114Sgblack@eecs.umich.edu DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n"); 2175114Sgblack@eecs.umich.edu doneSquashing = false; 2185114Sgblack@eecs.umich.edu 2195114Sgblack@eecs.umich.edu squashedSeqNum = squash_num; 2205114Sgblack@eecs.umich.edu 2215114Sgblack@eecs.umich.edu assert(tail != cpu->instList.end()); 2225114Sgblack@eecs.umich.edu 2235851Sgblack@eecs.umich.edu squashIt = tail; 2245114Sgblack@eecs.umich.edu 2255114Sgblack@eecs.umich.edu doSquash(); 2265114Sgblack@eecs.umich.edu} 2275114Sgblack@eecs.umich.edu 2285114Sgblack@eecs.umich.edutemplate <class Impl> 2295114Sgblack@eecs.umich.eduuint64_t 2305114Sgblack@eecs.umich.eduROB<Impl>::readHeadPC() 2315851Sgblack@eecs.umich.edu{ 2325114Sgblack@eecs.umich.edu assert(numInstsInROB == countInsts()); 2335114Sgblack@eecs.umich.edu 2345114Sgblack@eecs.umich.edu DynInstPtr head_inst = cpu->instList.front(); 2355114Sgblack@eecs.umich.edu 2365114Sgblack@eecs.umich.edu return head_inst->readPC(); 2375114Sgblack@eecs.umich.edu} 2385114Sgblack@eecs.umich.edu 2395851Sgblack@eecs.umich.edutemplate <class Impl> 2405114Sgblack@eecs.umich.eduuint64_t 2415114Sgblack@eecs.umich.eduROB<Impl>::readHeadNextPC() 2425114Sgblack@eecs.umich.edu{ 2435114Sgblack@eecs.umich.edu assert(numInstsInROB == countInsts()); 2445114Sgblack@eecs.umich.edu 2455114Sgblack@eecs.umich.edu DynInstPtr head_inst = cpu->instList.front(); 2465114Sgblack@eecs.umich.edu 2475851Sgblack@eecs.umich.edu return head_inst->readNextPC(); 2485114Sgblack@eecs.umich.edu} 2495114Sgblack@eecs.umich.edu 2505114Sgblack@eecs.umich.edutemplate <class Impl> 2515114Sgblack@eecs.umich.eduInstSeqNum 2525114Sgblack@eecs.umich.eduROB<Impl>::readHeadSeqNum() 2535114Sgblack@eecs.umich.edu{ 2545114Sgblack@eecs.umich.edu // Return the last sequence number that has not been squashed. Other 2555851Sgblack@eecs.umich.edu // stages can use it to squash any instructions younger than the current 2565114Sgblack@eecs.umich.edu // tail. 2575114Sgblack@eecs.umich.edu DynInstPtr head_inst = cpu->instList.front(); 2585114Sgblack@eecs.umich.edu 2595114Sgblack@eecs.umich.edu return head_inst->seqNum; 2605114Sgblack@eecs.umich.edu} 2615114Sgblack@eecs.umich.edu 2625114Sgblack@eecs.umich.edutemplate <class Impl> 2635857Sgblack@eecs.umich.eduuint64_t 2645114Sgblack@eecs.umich.eduROB<Impl>::readTailPC() 2655114Sgblack@eecs.umich.edu{ 2665114Sgblack@eecs.umich.edu assert(numInstsInROB == countInsts()); 2675114Sgblack@eecs.umich.edu 2685114Sgblack@eecs.umich.edu assert(tail != cpu->instList.end()); 2695114Sgblack@eecs.umich.edu 2705857Sgblack@eecs.umich.edu return (*tail)->readPC(); 2715857Sgblack@eecs.umich.edu} 2725114Sgblack@eecs.umich.edu 2735114Sgblack@eecs.umich.edutemplate <class Impl> 2745114Sgblack@eecs.umich.eduInstSeqNum 2755114Sgblack@eecs.umich.eduROB<Impl>::readTailSeqNum() 2765114Sgblack@eecs.umich.edu{ 2775114Sgblack@eecs.umich.edu // Return the last sequence number that has not been squashed. Other 2785857Sgblack@eecs.umich.edu // stages can use it to squash any instructions younger than the current 2795857Sgblack@eecs.umich.edu // tail. 2805114Sgblack@eecs.umich.edu return (*tail)->seqNum; 2815114Sgblack@eecs.umich.edu} 2825114Sgblack@eecs.umich.edu 2835114Sgblack@eecs.umich.edu#endif // __CPU_BETA_CPU_ROB_IMPL_HH__ 2845114Sgblack@eecs.umich.edu