rename_impl.hh revision 1061
11689SN/A#include <list> 29444SAndreas.Sandberg@ARM.com 39913Ssteve.reinhardt@amd.com#include "cpu/beta_cpu/rename.hh" 47854SAli.Saidi@ARM.com 57854SAli.Saidi@ARM.comtemplate <class Impl> 67854SAli.Saidi@ARM.comSimpleRename<Impl>::SimpleRename(Params ¶ms) 77854SAli.Saidi@ARM.com : iewToRenameDelay(params.iewToRenameDelay), 87854SAli.Saidi@ARM.com decodeToRenameDelay(params.decodeToRenameDelay), 97854SAli.Saidi@ARM.com commitToRenameDelay(params.commitToRenameDelay), 107854SAli.Saidi@ARM.com renameWidth(params.renameWidth), 117854SAli.Saidi@ARM.com commitWidth(params.commitWidth), 127854SAli.Saidi@ARM.com numInst(0) 137854SAli.Saidi@ARM.com{ 147854SAli.Saidi@ARM.com _status = Idle; 152329SN/A} 161689SN/A 171689SN/Atemplate <class Impl> 181689SN/Avoid 191689SN/ASimpleRename<Impl>::setCPU(FullCPU *cpu_ptr) 201689SN/A{ 211689SN/A DPRINTF(Rename, "Rename: Setting CPU pointer.\n"); 221689SN/A cpu = cpu_ptr; 231689SN/A} 241689SN/A 251689SN/Atemplate <class Impl> 261689SN/Avoid 271689SN/ASimpleRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 281689SN/A{ 291689SN/A DPRINTF(Rename, "Rename: Setting time buffer pointer.\n"); 301689SN/A timeBuffer = tb_ptr; 311689SN/A 321689SN/A // Setup wire to read information from time buffer, from IEW stage. 331689SN/A fromIEW = timeBuffer->getWire(-iewToRenameDelay); 341689SN/A 351689SN/A // Setup wire to read infromation from time buffer, from commit stage. 361689SN/A fromCommit = timeBuffer->getWire(-commitToRenameDelay); 371689SN/A 381689SN/A // Setup wire to write information to previous stages. 391689SN/A toDecode = timeBuffer->getWire(0); 402665Ssaidi@eecs.umich.edu} 412665Ssaidi@eecs.umich.edu 422935Sksewell@umich.edutemplate <class Impl> 431689SN/Avoid 441689SN/ASimpleRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr) 451060SN/A{ 461060SN/A DPRINTF(Rename, "Rename: Setting rename queue pointer.\n"); 473773Sgblack@eecs.umich.edu renameQueue = rq_ptr; 486329Sgblack@eecs.umich.edu 496658Snate@binkert.org // Setup wire to write information to future stages. 501717SN/A toIEW = renameQueue->getWire(0); 519913Ssteve.reinhardt@amd.com} 528232Snate@binkert.org 538232Snate@binkert.orgtemplate <class Impl> 549527SMatt.Horsnell@arm.comvoid 555529Snate@binkert.orgSimpleRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr) 561060SN/A{ 576221Snate@binkert.org DPRINTF(Rename, "Rename: Setting decode queue pointer.\n"); 586221Snate@binkert.org decodeQueue = dq_ptr; 591061SN/A 605529Snate@binkert.org // Setup wire to get information from decode. 614329Sktlim@umich.edu fromDecode = decodeQueue->getWire(-decodeToRenameDelay); 624329Sktlim@umich.edu 632292SN/A} 642292SN/A 652292SN/Atemplate <class Impl> 662292SN/Avoid 675529Snate@binkert.orgSimpleRename<Impl>::setRenameMap(RenameMap *rm_ptr) 682361SN/A{ 691060SN/A DPRINTF(Rename, "Rename: Setting rename map pointer.\n"); 702292SN/A renameMap = rm_ptr; 718907Slukefahr@umich.edu} 722292SN/A 732292SN/Atemplate <class Impl> 742292SN/Avoid 752292SN/ASimpleRename<Impl>::setFreeList(FreeList *fl_ptr) 762292SN/A{ 772292SN/A DPRINTF(Rename, "Rename: Setting free list pointer.\n"); 782292SN/A freeList = fl_ptr; 791060SN/A} 801060SN/A 811061SN/Atemplate <class Impl> 821060SN/Avoid 832292SN/ASimpleRename<Impl>::dumpHistory() 841062SN/A{ 851062SN/A typename list<RenameHistory>::iterator buf_it = historyBuffer.begin(); 868240Snate@binkert.org 871062SN/A while (buf_it != historyBuffer.end()) 881062SN/A { 891062SN/A cprintf("Seq num: %i\nArch reg: %i New phys reg: %i Old phys " 908240Snate@binkert.org "reg: %i\n", (*buf_it).instSeqNum, (int)(*buf_it).archReg, 911062SN/A (int)(*buf_it).newPhysReg, (int)(*buf_it).prevPhysReg); 921062SN/A 931062SN/A buf_it++; 948240Snate@binkert.org } 951062SN/A} 961062SN/A 972301SN/Atemplate <class Impl> 988240Snate@binkert.orgvoid 992301SN/ASimpleRename<Impl>::block() 1002301SN/A{ 1012292SN/A DPRINTF(Rename, "Rename: Blocking.\n"); 1028240Snate@binkert.org // Set status to Blocked. 1032292SN/A _status = Blocked; 1042292SN/A 1051062SN/A // Add the current inputs onto the skid buffer, so they can be 1068240Snate@binkert.org // reprocessed when this stage unblocks. 1071062SN/A skidBuffer.push(*fromDecode); 1081062SN/A 1091062SN/A // Note that this stage only signals previous stages to stall when 1108240Snate@binkert.org // it is the cause of the stall originates at this stage. Otherwise 1111062SN/A // the previous stages are expected to check all possible stall signals. 1121062SN/A} 1131062SN/A 1148240Snate@binkert.orgtemplate <class Impl> 1151062SN/Ainline void 1161062SN/ASimpleRename<Impl>::unblock() 1171062SN/A{ 1188240Snate@binkert.org DPRINTF(Rename, "Rename: Read instructions out of skid buffer this " 1192292SN/A "cycle.\n"); 1201062SN/A // Remove the now processed instructions from the skid buffer. 1211062SN/A skidBuffer.pop(); 1228240Snate@binkert.org 1232292SN/A // If there's still information in the skid buffer, then 1241062SN/A // continue to tell previous stages to stall. They will be 1252292SN/A // able to restart once the skid buffer is empty. 1268240Snate@binkert.org if (!skidBuffer.empty()) { 1272292SN/A toDecode->renameInfo.stall = true; 1282292SN/A } else { 1291062SN/A DPRINTF(Rename, "Rename: Done unblocking.\n"); 1308240Snate@binkert.org _status = Running; 1311062SN/A } 1321062SN/A} 1331062SN/A 1348240Snate@binkert.orgtemplate <class Impl> 1351062SN/Avoid 1361062SN/ASimpleRename<Impl>::doSquash() 1371062SN/A{ 1388240Snate@binkert.org typename list<RenameHistory>::iterator hb_it = historyBuffer.begin(); 1391062SN/A// typename list<RenameHistory>::iterator delete_it; 1401062SN/A 1411062SN/A InstSeqNum squashed_seq_num = fromCommit->commitInfo.doneSeqNum; 1428240Snate@binkert.org 1431062SN/A#ifdef FULL_SYSTEM 1441062SN/A assert(!historyBuffer.empty()); 1451062SN/A#else 1468240Snate@binkert.org // After a syscall squashes everything, the history buffer may be empty 1471062SN/A // but the ROB may still be squashing instructions. 1481062SN/A if (historyBuffer.empty()) { 1492301SN/A return; 1508240Snate@binkert.org } 1512301SN/A#endif // FULL_SYSTEM 1522301SN/A 1532301SN/A // Go through the most recent instructions, undoing the mappings 1542301SN/A // they did and freeing up the registers. 1558240Snate@binkert.org while ((*hb_it).instSeqNum > squashed_seq_num) 1562301SN/A { 1572301SN/A DPRINTF(Rename, "Rename: Removing history entry with sequence " 1582301SN/A "number %i.\n", (*hb_it).instSeqNum); 1592307SN/A 1608240Snate@binkert.org // If it's not simply a place holder, then add the registers. 1612307SN/A if (!(*hb_it).placeHolder) { 1622307SN/A // Tell the rename map to set the architected register to the 1632307SN/A // previous physical register that it was renamed to. 1647897Shestness@cs.utexas.edu renameMap->setEntry(hb_it->archReg, hb_it->prevPhysReg); 1658240Snate@binkert.org 1667897Shestness@cs.utexas.edu // Put the renamed physical register back on the free list. 1677897Shestness@cs.utexas.edu freeList->addReg(hb_it->newPhysReg); 1687897Shestness@cs.utexas.edu } 1698240Snate@binkert.org 1707897Shestness@cs.utexas.edu// delete_it = hb_it; 1717897Shestness@cs.utexas.edu 1721062SN/A// hb_it++; 1731062SN/A 1741062SN/A historyBuffer.erase(hb_it++); 1751062SN/A 1762292SN/A assert(hb_it != historyBuffer.end()); 1771060SN/A } 1781060SN/A} 1791060SN/A 1801060SN/Atemplate <class Impl> 1811060SN/Avoid 1821060SN/ASimpleRename<Impl>::squash() 1831060SN/A{ 1841060SN/A DPRINTF(Rename, "Rename: Squashing instructions.\n"); 1851060SN/A // Set the status to Squashing. 1861060SN/A _status = Squashing; 1871060SN/A 1881060SN/A numInst = 0; 1891060SN/A 1901061SN/A // Clear the skid buffer in case it has any data in it. 1911060SN/A while (!skidBuffer.empty()) 1922292SN/A { 1931060SN/A skidBuffer.pop(); 1941060SN/A } 1951060SN/A 1961060SN/A doSquash(); 1971060SN/A} 1981060SN/A 1991060SN/A// In the future, when a SmartPtr is used for DynInst, then this function 2001061SN/A// itself can handle returning the instruction's physical registers to 2011060SN/A// the free list. 2022292SN/Atemplate<class Impl> 2031060SN/Avoid 2041060SN/ASimpleRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num) 2051060SN/A{ 2061060SN/A DPRINTF(Rename, "Rename: Removing a committed instruction from the " 2071060SN/A "history buffer, until sequence number %lli.\n", inst_seq_num); 2081060SN/A typename list<RenameHistory>::iterator hb_it = historyBuffer.end(); 2091060SN/A 2101061SN/A --hb_it; 2111060SN/A 2129427SAndreas.Sandberg@ARM.com if (hb_it->instSeqNum > inst_seq_num) { 2131060SN/A DPRINTF(Rename, "Rename: Old sequence number encountered. Ensure " 2149444SAndreas.Sandberg@ARM.com "that a syscall happened recently.\n"); 2159444SAndreas.Sandberg@ARM.com return; 2169444SAndreas.Sandberg@ARM.com } 2179444SAndreas.Sandberg@ARM.com 2189444SAndreas.Sandberg@ARM.com while ((*hb_it).instSeqNum != inst_seq_num) 2199444SAndreas.Sandberg@ARM.com { 2209444SAndreas.Sandberg@ARM.com // Make sure we haven't gone off the end of the list. 2219444SAndreas.Sandberg@ARM.com assert(hb_it != historyBuffer.end()); 2229444SAndreas.Sandberg@ARM.com 2239444SAndreas.Sandberg@ARM.com // In theory instructions at the end of the history buffer 2249444SAndreas.Sandberg@ARM.com // should be older than the instruction being removed, which 2259444SAndreas.Sandberg@ARM.com // means they will have a lower sequence number. Also the 2262329SN/A // instruction being removed from the history really should 2276221Snate@binkert.org // be the last instruction in the list, as it is the instruction 2289444SAndreas.Sandberg@ARM.com // that was just committed that is being removed. 2299444SAndreas.Sandberg@ARM.com assert(hb_it->instSeqNum < inst_seq_num); 2302292SN/A DPRINTF(Rename, "Rename: Freeing up older rename of reg %i, sequence" 2312292SN/A " number %i.\n", 2322292SN/A (*hb_it).prevPhysReg, (*hb_it).instSeqNum); 2332292SN/A 2349444SAndreas.Sandberg@ARM.com if (!(*hb_it).placeHolder) { 2359444SAndreas.Sandberg@ARM.com freeList->addReg((*hb_it).prevPhysReg); 2369444SAndreas.Sandberg@ARM.com } 2379444SAndreas.Sandberg@ARM.com 2389444SAndreas.Sandberg@ARM.com historyBuffer.erase(hb_it--); 2399444SAndreas.Sandberg@ARM.com } 2409444SAndreas.Sandberg@ARM.com 2419444SAndreas.Sandberg@ARM.com // Finally free up the previous register of the squashed instruction 2422292SN/A // itself. 2431060SN/A if (!(*hb_it).placeHolder) { 2441060SN/A freeList->addReg(hb_it->prevPhysReg); 2452292SN/A } 2462292SN/A 2476221Snate@binkert.org historyBuffer.erase(hb_it); 2482292SN/A 2492292SN/A} 2502292SN/A 2512292SN/Atemplate <class Impl> 2522292SN/Ainline void 2531061SN/ASimpleRename<Impl>::renameSrcRegs(DynInstPtr &inst) 2541060SN/A{ 2552292SN/A unsigned num_src_regs = inst->numSrcRegs(); 2561060SN/A 2576221Snate@binkert.org // Get the architectual register numbers from the source and 2586221Snate@binkert.org // destination operands, and redirect them to the right register. 2591060SN/A // Will need to mark dependencies though. 2601060SN/A for (int src_idx = 0; src_idx < num_src_regs; src_idx++) 2611061SN/A { 2621060SN/A RegIndex src_reg = inst->srcRegIdx(src_idx); 2632292SN/A 2641060SN/A // Look up the source registers to get the phys. register they've 2652292SN/A // been renamed to, and set the sources to those registers. 2662292SN/A RegIndex renamed_reg = renameMap->lookup(src_reg); 2671060SN/A 2682292SN/A DPRINTF(Rename, "Rename: Looking up arch reg %i, got " 2692292SN/A "physical reg %i.\n", (int)src_reg, (int)renamed_reg); 2702292SN/A 2712292SN/A inst->renameSrcReg(src_idx, renamed_reg); 2722292SN/A 2731060SN/A // Either incorporate it into the info passed back, 2741060SN/A // or make another function call to see if that register is 2751061SN/A // ready or not. 2762863Sktlim@umich.edu if (renameMap->isReady(renamed_reg)) { 2779444SAndreas.Sandberg@ARM.com DPRINTF(Rename, "Rename: Register is ready.\n"); 2781060SN/A 2799444SAndreas.Sandberg@ARM.com inst->markSrcRegReady(src_idx); 2809444SAndreas.Sandberg@ARM.com } 2819444SAndreas.Sandberg@ARM.com } 2829444SAndreas.Sandberg@ARM.com} 2839444SAndreas.Sandberg@ARM.com 2849444SAndreas.Sandberg@ARM.comtemplate <class Impl> 2859444SAndreas.Sandberg@ARM.cominline void 2862863Sktlim@umich.eduSimpleRename<Impl>::renameDestRegs(DynInstPtr &inst) 2872316SN/A{ 2881060SN/A typename SimpleRenameMap::RenameInfo rename_result; 2892316SN/A 2902316SN/A unsigned num_dest_regs = inst->numDestRegs(); 2912307SN/A 2921060SN/A // Rename the destination registers. 2939444SAndreas.Sandberg@ARM.com for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++) 2949444SAndreas.Sandberg@ARM.com { 2951060SN/A RegIndex dest_reg = inst->destRegIdx(dest_idx); 2969444SAndreas.Sandberg@ARM.com 2979444SAndreas.Sandberg@ARM.com // Get the physical register that the destination will be 2989444SAndreas.Sandberg@ARM.com // renamed to. 2999444SAndreas.Sandberg@ARM.com rename_result = renameMap->rename(dest_reg); 3006221Snate@binkert.org 3019444SAndreas.Sandberg@ARM.com DPRINTF(Rename, "Rename: Renaming arch reg %i to physical " 3029444SAndreas.Sandberg@ARM.com "reg %i.\n", (int)dest_reg, 3039444SAndreas.Sandberg@ARM.com (int)rename_result.first); 3049444SAndreas.Sandberg@ARM.com 3052307SN/A // Record the rename information so that a history can be kept. 3062307SN/A RenameHistory hb_entry(inst->seqNum, dest_reg, 3072307SN/A rename_result.first, 3082307SN/A rename_result.second); 3092307SN/A 3106221Snate@binkert.org historyBuffer.push_front(hb_entry); 3111858SN/A 3122292SN/A DPRINTF(Rename, "Rename: Adding instruction to history buffer, " 3131858SN/A "sequence number %lli.\n", 3142292SN/A (*historyBuffer.begin()).instSeqNum); 3152292SN/A 3162292SN/A // Tell the instruction to rename the appropriate destination 3172292SN/A // register (dest_idx) to the new physical register 3183788Sgblack@eecs.umich.edu // (rename_result.first), and record the previous physical 3192292SN/A // register that the same logical register was renamed to 3202698Sktlim@umich.edu // (rename_result.second). 3213788Sgblack@eecs.umich.edu inst->renameDestReg(dest_idx, 3222301SN/A rename_result.first, 3233788Sgblack@eecs.umich.edu rename_result.second); 3243788Sgblack@eecs.umich.edu } 3253788Sgblack@eecs.umich.edu 3263788Sgblack@eecs.umich.edu // If it's an instruction with no destination registers, then put 3273788Sgblack@eecs.umich.edu // a placeholder within the history buffer. It might be better 3283788Sgblack@eecs.umich.edu // to not put it in the history buffer at all (other than branches, 3293788Sgblack@eecs.umich.edu // which always need at least a place holder), and differentiate 3303788Sgblack@eecs.umich.edu // between instructions with and without destination registers 3313788Sgblack@eecs.umich.edu // when getting from commit the instructions that committed. 3323788Sgblack@eecs.umich.edu if (num_dest_regs == 0) { 3333788Sgblack@eecs.umich.edu RenameHistory hb_entry(inst->seqNum); 3342292SN/A 3352292SN/A historyBuffer.push_front(hb_entry); 3362292SN/A 3372292SN/A DPRINTF(Rename, "Rename: Adding placeholder instruction to " 3382292SN/A "history buffer, sequence number %lli.\n", 3392329SN/A inst->seqNum); 3402292SN/A } 3412292SN/A} 3422292SN/A 3432935Sksewell@umich.edutemplate <class Impl> 3442935Sksewell@umich.eduinline int 3452731Sktlim@umich.eduSimpleRename<Impl>::calcFreeROBEntries() 3462292SN/A{ 3472292SN/A return fromCommit->commitInfo.freeROBEntries - 3482292SN/A renameWidth * iewToRenameDelay; 3492935Sksewell@umich.edu} 3502292SN/A 3512292SN/Atemplate <class Impl> 3522935Sksewell@umich.eduinline int 3534632Sgblack@eecs.umich.eduSimpleRename<Impl>::calcFreeIQEntries() 3543093Sksewell@umich.edu{ 3552292SN/A return fromIEW->iewInfo.freeIQEntries - renameWidth * iewToRenameDelay; 3562292SN/A} 3573093Sksewell@umich.edu 3584632Sgblack@eecs.umich.edutemplate<class Impl> 3592935Sksewell@umich.eduvoid 3602292SN/ASimpleRename<Impl>::tick() 3612292SN/A{ 3622292SN/A // Rename will need to try to rename as many instructions as it 3632292SN/A // has bandwidth, unless it is blocked. 3642292SN/A 3652292SN/A // Check if _status is BarrierStall. If so, then check if the number 3662292SN/A // of free ROB entries is equal to the number of total ROB entries. 3672292SN/A // Once equal then wake this stage up. Set status to unblocking maybe. 3682292SN/A 3692292SN/A if (_status != Blocked && _status != Squashing) { 3702292SN/A DPRINTF(Rename, "Rename: Status is not blocked, will attempt to " 3712292SN/A "run stage.\n"); 3722292SN/A // Make sure that the skid buffer has something in it if the 3732292SN/A // status is unblocking. 3742292SN/A assert(_status == Unblocking ? !skidBuffer.empty() : 1); 3752292SN/A 3766221Snate@binkert.org rename(); 3776221Snate@binkert.org 3782292SN/A // If the status was unblocking, then instructions from the skid 3792292SN/A // buffer were used. Remove those instructions and handle 3803867Sbinkertn@umich.edu // the rest of unblocking. 3816221Snate@binkert.org if (_status == Unblocking) { 3822292SN/A if (fromDecode->size > 0) { 3832292SN/A // Add the current inputs onto the skid buffer, so they can be 3842292SN/A // reprocessed when this stage unblocks. 3852292SN/A skidBuffer.push(*fromDecode); 3862292SN/A } 3872292SN/A 3882292SN/A unblock(); 3892292SN/A } 3902292SN/A } else if (_status == Blocked) { 3912292SN/A // If stage is blocked and still receiving valid instructions, 3922292SN/A // make sure to store them in the skid buffer. 3932292SN/A if (fromDecode->size > 0) { 3942292SN/A 3952292SN/A block(); 3962292SN/A 3972292SN/A // Continue to tell previous stage to stall. 3982292SN/A toDecode->renameInfo.stall = true; 3993867Sbinkertn@umich.edu } 4002292SN/A 4013867Sbinkertn@umich.edu if (!fromIEW->iewInfo.stall && 4026221Snate@binkert.org !fromCommit->commitInfo.stall && 4032292SN/A calcFreeROBEntries() > 0 && 4042292SN/A calcFreeIQEntries() > 0 && 4052292SN/A renameMap->numFreeEntries() > 0) { 4062292SN/A 4072292SN/A // Need to be sure to check all blocking conditions above. 4082292SN/A // If they have cleared, then start unblocking. 4092292SN/A DPRINTF(Rename, "Rename: Stall signals cleared, going to " 4102292SN/A "unblock.\n"); 4112292SN/A _status = Unblocking; 4122292SN/A 4132292SN/A // Continue to tell previous stage to block until this stage 4142292SN/A // is done unblocking. 4156221Snate@binkert.org toDecode->renameInfo.stall = true; 4162292SN/A } else { 4172292SN/A // Otherwise no conditions have changed. Tell previous 4182292SN/A // stage to continue blocking. 4192292SN/A toDecode->renameInfo.stall = true; 4202292SN/A } 4212292SN/A 4222292SN/A if (fromCommit->commitInfo.squash || 4232292SN/A fromCommit->commitInfo.robSquashing) { 4242292SN/A squash(); 4256221Snate@binkert.org return; 4262292SN/A } 4272292SN/A } else if (_status == Squashing) { 4282292SN/A if (fromCommit->commitInfo.squash) { 4292292SN/A squash(); 4302292SN/A } else if (!fromCommit->commitInfo.squash && 4312292SN/A !fromCommit->commitInfo.robSquashing) { 4322292SN/A 4332292SN/A DPRINTF(Rename, "Rename: Done squashing, going to running.\n"); 4342292SN/A _status = Running; 4352292SN/A } else { 4362292SN/A doSquash(); 4372292SN/A } 4382301SN/A } 4392301SN/A 4403788Sgblack@eecs.umich.edu // Ugly code, revamp all of the tick() functions eventually. 4413788Sgblack@eecs.umich.edu if (fromCommit->commitInfo.doneSeqNum != 0 && _status != Squashing) { 4423788Sgblack@eecs.umich.edu removeFromHistory(fromCommit->commitInfo.doneSeqNum); 4433788Sgblack@eecs.umich.edu } 4443788Sgblack@eecs.umich.edu 4453788Sgblack@eecs.umich.edu // Perhaps put this outside of this function, since this will 4463788Sgblack@eecs.umich.edu // happen regardless of whether or not the stage is blocked or 4473788Sgblack@eecs.umich.edu // squashing. 4483798Sgblack@eecs.umich.edu // Read from the time buffer any necessary data. 4493798Sgblack@eecs.umich.edu // Read registers that are freed, and add them to the freelist. 4503798Sgblack@eecs.umich.edu // This is unnecessary due to the history buffer (assuming the history 4513798Sgblack@eecs.umich.edu // buffer works properly). 4523798Sgblack@eecs.umich.edu/* 4533798Sgblack@eecs.umich.edu while(!fromCommit->commitInfo.freeRegs.empty()) 4542292SN/A { 4552292SN/A PhysRegIndex freed_reg = fromCommit->commitInfo.freeRegs.back(); 4562292SN/A DPRINTF(Rename, "Rename: Adding freed register %i to freelist.\n", 4572292SN/A (int)freed_reg); 4582292SN/A freeList->addReg(freed_reg); 4592292SN/A 4602292SN/A fromCommit->commitInfo.freeRegs.pop_back(); 4612292SN/A } 4622292SN/A*/ 4632292SN/A 4642292SN/A} 4652292SN/A 4662292SN/Atemplate<class Impl> 4672292SN/Avoid 4682292SN/ASimpleRename<Impl>::rename() 4692292SN/A{ 4702292SN/A // Check if any of the stages ahead of rename are telling rename 4712292SN/A // to squash. The squash() function will also take care of fixing up 4722292SN/A // the rename map and the free list. 4732292SN/A if (fromCommit->commitInfo.squash || 4741858SN/A fromCommit->commitInfo.robSquashing) { 4751858SN/A DPRINTF(Rename, "Rename: Receiving signal from Commit to squash.\n"); 4761858SN/A squash(); 4771858SN/A return; 4781858SN/A } 4796221Snate@binkert.org 4801858SN/A // Check if time buffer is telling this stage to stall. 4812292SN/A if (fromIEW->iewInfo.stall || 4822292SN/A fromCommit->commitInfo.stall) { 4832292SN/A DPRINTF(Rename, "Rename: Receiving signal from IEW/Commit to " 4842292SN/A "stall.\n"); 4851858SN/A block(); 4862292SN/A return; 4872292SN/A } 4882292SN/A 4892292SN/A // Check if the current status is squashing. If so, set its status 4902292SN/A // to running and resume execution the next cycle. 4912292SN/A if (_status == Squashing) { 4922292SN/A DPRINTF(Rename, "Rename: Done squashing.\n"); 4932292SN/A _status = Running; 4942292SN/A return; 4952292SN/A } 4962292SN/A 4972292SN/A // Check the decode queue to see if instructions are available. 4982292SN/A // If there are no available instructions to rename, then do nothing. 4991858SN/A // Or, if the stage is currently unblocking, then go ahead and run it. 5002292SN/A if (fromDecode->size == 0 && _status != Unblocking) { 5012292SN/A DPRINTF(Rename, "Rename: Nothing to do, breaking out early.\n"); 5022292SN/A // Should I change status to idle? 5032292SN/A return; 5042292SN/A } 5052292SN/A 5062292SN/A //////////////////////////////////// 5072292SN/A // Actual rename part. 5082292SN/A //////////////////////////////////// 5092292SN/A 5102292SN/A DynInstPtr inst; 5112292SN/A 5122292SN/A // If we're unblocking, then we may be in the middle of an instruction 5132292SN/A // group. Subtract off numInst to get the proper number of instructions 5142292SN/A // left. 5152292SN/A int insts_available = _status == Unblocking ? 5162292SN/A skidBuffer.front().size - numInst : 5172292SN/A fromDecode->size; 5182292SN/A 5192292SN/A bool block_this_cycle = false; 5202292SN/A 5212292SN/A // Will have to do a different calculation for the number of free 5222292SN/A // entries. Number of free entries recorded on this cycle - 5232292SN/A // renameWidth * renameToDecodeDelay 5242292SN/A int free_rob_entries = calcFreeROBEntries(); 5252292SN/A int free_iq_entries = calcFreeIQEntries(); 5262292SN/A int min_iq_rob = min(free_rob_entries, free_iq_entries); 5272292SN/A 5282292SN/A unsigned to_iew_index = 0; 5292292SN/A 5302292SN/A // Check if there's any space left. 5312292SN/A if (min_iq_rob <= 0) { 5322292SN/A DPRINTF(Rename, "Rename: Blocking due to no free ROB or IQ " 5332292SN/A "entries.\n" 5342292SN/A "Rename: ROB has %d free entries.\n" 5352292SN/A "Rename: IQ has %d free entries.\n", 5362292SN/A free_rob_entries, 5372292SN/A free_iq_entries); 5382292SN/A block(); 5392292SN/A // Tell previous stage to stall. 5402292SN/A toDecode->renameInfo.stall = true; 5412292SN/A 5422292SN/A return; 5432292SN/A } else if (min_iq_rob < insts_available) { 5442292SN/A DPRINTF(Rename, "Rename: Will have to block this cycle. Only " 5452292SN/A "%i insts can be renamed due to IQ/ROB limits.\n", 5462292SN/A min_iq_rob); 5472292SN/A 5482292SN/A insts_available = min_iq_rob; 5492292SN/A 5502292SN/A block_this_cycle = true; 5512292SN/A } 5522292SN/A 5532292SN/A while (insts_available > 0) { 5542292SN/A DPRINTF(Rename, "Rename: Sending instructions to iew.\n"); 5552292SN/A 5562292SN/A // Get the next instruction either from the skid buffer or the 5572292SN/A // decode queue. 5582292SN/A inst = _status == Unblocking ? skidBuffer.front().insts[numInst] : 5592292SN/A fromDecode->insts[numInst]; 5602292SN/A 5612292SN/A if (inst->isSquashed()) { 5622292SN/A DPRINTF(Rename, "Rename: instruction %i with PC %#x is " 5632292SN/A "squashed, skipping.\n", 5642292SN/A inst->seqNum, inst->readPC()); 5652292SN/A 5662292SN/A // Go to the next instruction. 5672292SN/A ++numInst; 5682292SN/A 5692292SN/A // Decrement how many instructions are available. 5702292SN/A --insts_available; 5712292SN/A 5722292SN/A continue; 5732292SN/A } 5742292SN/A 5752292SN/A DPRINTF(Rename, "Rename: Processing instruction %i with PC %#x.\n", 5762292SN/A inst->seqNum, inst->readPC()); 5772292SN/A 5782292SN/A // If it's a trap instruction, then it needs to wait here within 5792292SN/A // rename until the ROB is empty. Needs a way to detect that the 5802292SN/A // ROB is empty. Maybe an event? 5812292SN/A // Would be nice if it could be avoided putting this into a 5822292SN/A // specific stage and instead just put it into the AlphaFullCPU. 5832292SN/A // Might not really be feasible though... 5842292SN/A // (EXCB, TRAPB) 5857720Sgblack@eecs.umich.edu if (inst->isSerializing()) { 5867720Sgblack@eecs.umich.edu panic("Rename: Serializing instruction encountered.\n"); 5872292SN/A DPRINTF(Rename, "Rename: Serializing instruction " 5882292SN/A "encountered.\n"); 5892292SN/A 5907720Sgblack@eecs.umich.edu // Change status over to BarrierStall so that other stages know 5917720Sgblack@eecs.umich.edu // what this is blocked on. 5927720Sgblack@eecs.umich.edu _status = BarrierStall; 5932292SN/A 5942292SN/A block_this_cycle = true; 5952292SN/A 5962292SN/A break; 5972292SN/A } 5982292SN/A 5992292SN/A // Check here to make sure there are enough destination registers 6002292SN/A // to rename to. Otherwise block. 6012292SN/A if (renameMap->numFreeEntries() < inst->numDestRegs()) 6022292SN/A { 6037720Sgblack@eecs.umich.edu DPRINTF(Rename, "Rename: Blocking due to lack of free " 6042292SN/A "physical registers to rename to.\n"); 6059531Sgeoffrey.blake@arm.com // Need some sort of event based on a register being freed. 6069531Sgeoffrey.blake@arm.com 6079531Sgeoffrey.blake@arm.com block_this_cycle = true; 6089531Sgeoffrey.blake@arm.com 6099531Sgeoffrey.blake@arm.com break; 6109531Sgeoffrey.blake@arm.com } 6119531Sgeoffrey.blake@arm.com 6129531Sgeoffrey.blake@arm.com renameSrcRegs(inst); 6139531Sgeoffrey.blake@arm.com 6149531Sgeoffrey.blake@arm.com renameDestRegs(inst); 6159531Sgeoffrey.blake@arm.com 6169531Sgeoffrey.blake@arm.com // Put instruction in rename queue. 6172292SN/A toIEW->insts[to_iew_index] = inst; 6182292SN/A ++(toIEW->size); 6192292SN/A 6202292SN/A // Decrease the number of free ROB and IQ entries. 6212336SN/A --free_rob_entries; 6222336SN/A --free_iq_entries; 6232336SN/A 6242336SN/A // Increment which instruction we're on. 6252336SN/A ++to_iew_index; 6262336SN/A ++numInst; 6272336SN/A 6282336SN/A // Decrement how many instructions are available. 6292292SN/A --insts_available; 6302292SN/A } 6312301SN/A 6322301SN/A // Check if there's any instructions left that haven't yet been renamed. 6332292SN/A // If so then block. 6342301SN/A if (block_this_cycle) { 6352301SN/A block(); 6362301SN/A 6372292SN/A toDecode->renameInfo.stall = true; 6382301SN/A } else { 6392292SN/A // If we had a successful rename and didn't have to exit early, then 6402301SN/A // reset numInst so it will refer to the correct instruction on next 6412292SN/A // run. 6422301SN/A numInst = 0; 6432292SN/A } 6442292SN/A} 6452292SN/A