rob_impl.hh revision 1060
11689SN/A#ifndef __ROB_IMPL_HH__ 29444SAndreas.Sandberg@ARM.com#define __ROB_IMPL_HH__ 39444SAndreas.Sandberg@ARM.com 49444SAndreas.Sandberg@ARM.com#include "cpu/beta_cpu/rob.hh" 59444SAndreas.Sandberg@ARM.com 69444SAndreas.Sandberg@ARM.comtemplate<class Impl> 79444SAndreas.Sandberg@ARM.comROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth) 89444SAndreas.Sandberg@ARM.com : numEntries(_numEntries), 99444SAndreas.Sandberg@ARM.com squashWidth(_squashWidth), 109444SAndreas.Sandberg@ARM.com numInstsInROB(0), 119444SAndreas.Sandberg@ARM.com squashedSeqNum(0) 129444SAndreas.Sandberg@ARM.com{ 139444SAndreas.Sandberg@ARM.com doneSquashing = true; 142329SN/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 tail = cpu->instList.begin(); 231689SN/A 241689SN/A squashIt = cpu->instList.end(); 251689SN/A} 261689SN/A 271689SN/Atemplate<class Impl> 281689SN/Aint 291689SN/AROB<Impl>::countInsts() 301689SN/A{ 311689SN/A/* 321689SN/A int return_val = 0; 331689SN/A 341689SN/A // Iterate through the ROB from the head to the tail, counting the 351689SN/A // entries. 361689SN/A for (InstIt i = cpu->instList.begin(); i != tail; i++) 371689SN/A { 381689SN/A assert(i != cpu->instList.end()); 392665Ssaidi@eecs.umich.edu return_val++; 402665Ssaidi@eecs.umich.edu } 412831Sksewell@umich.edu 421689SN/A return return_val; 431689SN/A*/ 449944Smatt.horsnell@ARM.com // Because the head won't be tracked properly until the ROB gets the 459944Smatt.horsnell@ARM.com // first instruction, and any time that the ROB is empty and has not 469944Smatt.horsnell@ARM.com // yet gotten the instruction, this function doesn't work. 476221Snate@binkert.org return numInstsInROB; 486221Snate@binkert.org} 491717SN/A 508232Snate@binkert.orgtemplate<class Impl> 518232Snate@binkert.orgvoid 529954SFaissal.Sleiman@arm.comROB<Impl>::insertInst(DynInst *inst) 531060SN/A{ 546221Snate@binkert.org // Make sure we have the right number of instructions. 552292SN/A assert(numInstsInROB == countInsts()); 561061SN/A // Make sure the instruction is valid. 579954SFaissal.Sleiman@arm.com assert(inst); 584329Sktlim@umich.edu 599954SFaissal.Sleiman@arm.com DPRINTF(ROB, "ROB: Adding inst PC %#x to the ROB.\n", inst->readPC()); 609954SFaissal.Sleiman@arm.com 611060SN/A // If the ROB is full then exit. 629954SFaissal.Sleiman@arm.com assert(numInstsInROB != numEntries); 631060SN/A 649954SFaissal.Sleiman@arm.com ++numInstsInROB; 652292SN/A 662292SN/A // Increment the tail iterator, moving it one instruction back. 672292SN/A // There is a special case if the ROB was empty prior to this insertion, 682292SN/A // in which case the tail will be pointing at instList.end(). If that 692292SN/A // happens, then reset the tail to the beginning of the list. 702292SN/A if (tail != cpu->instList.end()) { 712292SN/A tail++; 722292SN/A } else { 732292SN/A tail = cpu->instList.begin(); 742292SN/A } 756221Snate@binkert.org 766221Snate@binkert.org // Make sure the tail iterator is actually pointing at the instruction 772292SN/A // added. 782292SN/A assert((*tail) == inst); 792292SN/A 802292SN/A DPRINTF(ROB, "ROB: Now has %d instructions.\n", numInstsInROB); 814329Sktlim@umich.edu 822292SN/A} 832292SN/A 842292SN/A// Whatever calls this function needs to ensure that it properly frees up 852292SN/A// registers prior to this function. 862292SN/Atemplate<class Impl> 876221Snate@binkert.orgvoid 886221Snate@binkert.orgROB<Impl>::retireHead() 892292SN/A{ 902292SN/A assert(numInstsInROB == countInsts()); 912292SN/A 922292SN/A DynInst *head_inst; 934329Sktlim@umich.edu 942292SN/A // Get the head ROB instruction. 959954SFaissal.Sleiman@arm.com head_inst = cpu->instList.front(); 962292SN/A 972292SN/A // Make certain this can retire. 986221Snate@binkert.org assert(head_inst->readyToCommit()); 996221Snate@binkert.org 1002292SN/A DPRINTF(ROB, "ROB: Retiring head instruction of the ROB, " 1012292SN/A "instruction PC %#x, seq num %i\n", head_inst->readPC(), 1022292SN/A head_inst->seqNum); 1032292SN/A 1042292SN/A // Keep track of how many instructions are in the ROB. 1051060SN/A --numInstsInROB; 1069444SAndreas.Sandberg@ARM.com 1079444SAndreas.Sandberg@ARM.com // Tell CPU to remove the instruction from the list of instructions. 1089444SAndreas.Sandberg@ARM.com // A special case is needed if the instruction being retired is the 1099444SAndreas.Sandberg@ARM.com // only instruction in the ROB; otherwise the tail iterator will become 1109444SAndreas.Sandberg@ARM.com // invalidated. 1119444SAndreas.Sandberg@ARM.com if (tail == cpu->instList.begin()) { 1129444SAndreas.Sandberg@ARM.com cpu->removeFrontInst(head_inst); 1139444SAndreas.Sandberg@ARM.com tail = cpu->instList.end(); 1149444SAndreas.Sandberg@ARM.com } else { 1159444SAndreas.Sandberg@ARM.com cpu->removeFrontInst(head_inst); 1166221Snate@binkert.org } 1179444SAndreas.Sandberg@ARM.com} 1182292SN/A 1199444SAndreas.Sandberg@ARM.comtemplate<class Impl> 1201060SN/Abool 1212292SN/AROB<Impl>::isHeadReady() 1222292SN/A{ 1232292SN/A if (numInstsInROB != 0) { 1242292SN/A DynInst *head_inst = cpu->instList.front(); 1252292SN/A 1262292SN/A return head_inst->readyToCommit(); 1272292SN/A } 1284329Sktlim@umich.edu 1294329Sktlim@umich.edu return false; 1304329Sktlim@umich.edu} 1314329Sktlim@umich.edu 1324329Sktlim@umich.edutemplate<class Impl> 1334329Sktlim@umich.eduunsigned 1344329Sktlim@umich.eduROB<Impl>::numFreeEntries() 1352292SN/A{ 1366221Snate@binkert.org assert(numInstsInROB == countInsts()); 1372292SN/A 1382292SN/A return numEntries - numInstsInROB; 1392292SN/A} 1402292SN/A 1412292SN/Atemplate<class Impl> 1422307SN/Avoid 1432307SN/AROB<Impl>::doSquash() 1449444SAndreas.Sandberg@ARM.com{ 1452307SN/A DPRINTF(ROB, "ROB: Squashing instructions.\n"); 1469444SAndreas.Sandberg@ARM.com 1479444SAndreas.Sandberg@ARM.com assert(squashIt != cpu->instList.end()); 1489444SAndreas.Sandberg@ARM.com 1492307SN/A for (int numSquashed = 0; 1502307SN/A numSquashed < squashWidth && (*squashIt)->seqNum != squashedSeqNum; 1512307SN/A ++numSquashed) 1522307SN/A { 1532307SN/A // Ensure that the instruction is younger. 1542307SN/A assert((*squashIt)->seqNum > squashedSeqNum); 1559444SAndreas.Sandberg@ARM.com 1562307SN/A DPRINTF(ROB, "ROB: Squashing instruction PC %#x, seq num %i.\n", 1572292SN/A (*squashIt)->readPC(), (*squashIt)->seqNum); 1582292SN/A 1592292SN/A // Mark the instruction as squashed, and ready to commit so that 1602292SN/A // it can drain out of the pipeline. 1612292SN/A (*squashIt)->setSquashed(); 1622292SN/A 1633867Sbinkertn@umich.edu (*squashIt)->setCanCommit(); 1642292SN/A 1656221Snate@binkert.org#ifndef FULL_SYSTEM 1666221Snate@binkert.org if (squashIt == cpu->instList.begin()) { 1672292SN/A DPRINTF(ROB, "ROB: Reached head of instruction list while " 1683867Sbinkertn@umich.edu "squashing.\n"); 1696221Snate@binkert.org 1703867Sbinkertn@umich.edu squashIt = cpu->instList.end(); 1712292SN/A 1723867Sbinkertn@umich.edu doneSquashing = true; 1732292SN/A 1743867Sbinkertn@umich.edu return; 1752292SN/A } 1762292SN/A#endif 1772292SN/A 1782292SN/A // Move the tail iterator to the next instruction. 1792292SN/A squashIt--; 1802292SN/A } 1812292SN/A 1826221Snate@binkert.org 1832292SN/A // Check if ROB is done squashing. 1842292SN/A if ((*squashIt)->seqNum == squashedSeqNum) { 1852292SN/A DPRINTF(ROB, "ROB: Done squashing instructions.\n"); 1862292SN/A 1872292SN/A squashIt = cpu->instList.end(); 1882292SN/A 1891060SN/A doneSquashing = true; 1901060SN/A } 1911061SN/A} 1921060SN/A 1931060SN/Atemplate<class Impl> 1941060SN/Avoid 1956221Snate@binkert.orgROB<Impl>::squash(InstSeqNum squash_num) 1961061SN/A{ 1976221Snate@binkert.org DPRINTF(ROB, "ROB: Starting to squash within the ROB.\n"); 1986221Snate@binkert.org doneSquashing = false; 1991060SN/A 2002292SN/A squashedSeqNum = squash_num; 2012292SN/A 2021060SN/A assert(tail != cpu->instList.end()); 2032292SN/A 2042292SN/A squashIt = tail; 2056221Snate@binkert.org 2062292SN/A doSquash(); 2072292SN/A} 2081060SN/A 2091060SN/Atemplate<class Impl> 2101061SN/Auint64_t 2111060SN/AROB<Impl>::readHeadPC() 2121061SN/A{ 2131060SN/A assert(numInstsInROB == countInsts()); 2141060SN/A 2151060SN/A DynInst *head_inst = cpu->instList.front(); 2167897Shestness@cs.utexas.edu 2177897Shestness@cs.utexas.edu return head_inst->readPC(); 2187720Sgblack@eecs.umich.edu} 2191060SN/A 2201060SN/Atemplate<class Impl> 2211060SN/Auint64_t 2226221Snate@binkert.orgROB<Impl>::readHeadNextPC() 2231060SN/A{ 2242292SN/A assert(numInstsInROB == countInsts()); 2252292SN/A 2262292SN/A DynInst *head_inst = cpu->instList.front(); 2272292SN/A 2282292SN/A return head_inst->readNextPC(); 2292292SN/A} 2301060SN/A 2311060SN/Atemplate<class Impl> 2322292SN/AInstSeqNum 2332292SN/AROB<Impl>::readHeadSeqNum() 2342292SN/A{ 2352292SN/A // Return the last sequence number that has not been squashed. Other 2362292SN/A // stages can use it to squash any instructions younger than the current 2372292SN/A // tail. 2382292SN/A DynInst *head_inst = cpu->instList.front(); 2392292SN/A 2402292SN/A return head_inst->seqNum; 2412292SN/A} 2421060SN/A 2431060SN/Atemplate<class Impl> 2442292SN/Auint64_t 2451060SN/AROB<Impl>::readTailPC() 2461060SN/A{ 2472292SN/A assert(numInstsInROB == countInsts()); 2482292SN/A 2496221Snate@binkert.org assert(tail != cpu->instList.end()); 2502292SN/A 2517897Shestness@cs.utexas.edu return (*tail)->readPC(); 2527897Shestness@cs.utexas.edu} 2531061SN/A 2541060SN/Atemplate<class Impl> 2551060SN/AInstSeqNum 2562292SN/AROB<Impl>::readTailSeqNum() 2571060SN/A{ 2582292SN/A // Return the last sequence number that has not been squashed. Other 2591858SN/A // stages can use it to squash any instructions younger than the current 2601060SN/A // tail. 2611060SN/A return (*tail)->seqNum; 2622292SN/A} 2637720Sgblack@eecs.umich.edu 2641060SN/A#endif // __ROB_IMPL_HH__ 2651060SN/A