rename_impl.hh revision 2665
11689SN/A/* 21689SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 31689SN/A * All rights reserved. 41689SN/A * 51689SN/A * Redistribution and use in source and binary forms, with or without 61689SN/A * modification, are permitted provided that the following conditions are 71689SN/A * met: redistributions of source code must retain the above copyright 81689SN/A * notice, this list of conditions and the following disclaimer; 91689SN/A * redistributions in binary form must reproduce the above copyright 101689SN/A * notice, this list of conditions and the following disclaimer in the 111689SN/A * documentation and/or other materials provided with the distribution; 121689SN/A * neither the name of the copyright holders nor the names of its 131689SN/A * contributors may be used to endorse or promote products derived from 141689SN/A * this software without specific prior written permission. 151689SN/A * 161689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Kevin Lim 291689SN/A */ 301689SN/A 311060SN/A#include <list> 321060SN/A 331858SN/A#include "config/full_system.hh" 341717SN/A#include "cpu/o3/rename.hh" 351060SN/A 361061SN/Atemplate <class Impl> 371060SN/ASimpleRename<Impl>::SimpleRename(Params ¶ms) 381060SN/A : iewToRenameDelay(params.iewToRenameDelay), 391060SN/A decodeToRenameDelay(params.decodeToRenameDelay), 401060SN/A commitToRenameDelay(params.commitToRenameDelay), 411060SN/A renameWidth(params.renameWidth), 421061SN/A commitWidth(params.commitWidth), 431061SN/A numInst(0) 441060SN/A{ 451060SN/A _status = Idle; 461060SN/A} 471060SN/A 481061SN/Atemplate <class Impl> 491060SN/Avoid 501062SN/ASimpleRename<Impl>::regStats() 511062SN/A{ 521062SN/A renameSquashCycles 531062SN/A .name(name() + ".renameSquashCycles") 541062SN/A .desc("Number of cycles rename is squashing") 551062SN/A .prereq(renameSquashCycles); 561062SN/A renameIdleCycles 571062SN/A .name(name() + ".renameIdleCycles") 581062SN/A .desc("Number of cycles rename is idle") 591062SN/A .prereq(renameIdleCycles); 601062SN/A renameBlockCycles 611062SN/A .name(name() + ".renameBlockCycles") 621062SN/A .desc("Number of cycles rename is blocking") 631062SN/A .prereq(renameBlockCycles); 641062SN/A renameUnblockCycles 651062SN/A .name(name() + ".renameUnblockCycles") 661062SN/A .desc("Number of cycles rename is unblocking") 671062SN/A .prereq(renameUnblockCycles); 681062SN/A renameRenamedInsts 691062SN/A .name(name() + ".renameRenamedInsts") 701062SN/A .desc("Number of instructions processed by rename") 711062SN/A .prereq(renameRenamedInsts); 721062SN/A renameSquashedInsts 731062SN/A .name(name() + ".renameSquashedInsts") 741062SN/A .desc("Number of squashed instructions processed by rename") 751062SN/A .prereq(renameSquashedInsts); 761062SN/A renameROBFullEvents 771062SN/A .name(name() + ".renameROBFullEvents") 781062SN/A .desc("Number of times rename has considered the ROB 'full'") 791062SN/A .prereq(renameROBFullEvents); 801062SN/A renameIQFullEvents 811062SN/A .name(name() + ".renameIQFullEvents") 821062SN/A .desc("Number of times rename has considered the IQ 'full'") 831062SN/A .prereq(renameIQFullEvents); 841062SN/A renameFullRegistersEvents 851062SN/A .name(name() + ".renameFullRegisterEvents") 861062SN/A .desc("Number of times there has been no free registers") 871062SN/A .prereq(renameFullRegistersEvents); 881062SN/A renameRenamedOperands 891062SN/A .name(name() + ".renameRenamedOperands") 901062SN/A .desc("Number of destination operands rename has renamed") 911062SN/A .prereq(renameRenamedOperands); 921062SN/A renameRenameLookups 931062SN/A .name(name() + ".renameRenameLookups") 941062SN/A .desc("Number of register rename lookups that rename has made") 951062SN/A .prereq(renameRenameLookups); 961062SN/A renameHBPlaceHolders 971062SN/A .name(name() + ".renameHBPlaceHolders") 981062SN/A .desc("Number of place holders added to the history buffer") 991062SN/A .prereq(renameHBPlaceHolders); 1001062SN/A renameCommittedMaps 1011062SN/A .name(name() + ".renameCommittedMaps") 1021062SN/A .desc("Number of HB maps that are committed") 1031062SN/A .prereq(renameCommittedMaps); 1041062SN/A renameUndoneMaps 1051062SN/A .name(name() + ".renameUndoneMaps") 1061062SN/A .desc("Number of HB maps that are undone due to squashing") 1071062SN/A .prereq(renameUndoneMaps); 1081062SN/A renameValidUndoneMaps 1091062SN/A .name(name() + ".renameValidUndoneMaps") 1101062SN/A .desc("Number of HB maps that are undone, and are not place holders") 1111062SN/A .prereq(renameValidUndoneMaps); 1121062SN/A} 1131062SN/A 1141062SN/Atemplate <class Impl> 1151062SN/Avoid 1161060SN/ASimpleRename<Impl>::setCPU(FullCPU *cpu_ptr) 1171060SN/A{ 1181060SN/A DPRINTF(Rename, "Rename: Setting CPU pointer.\n"); 1191060SN/A cpu = cpu_ptr; 1201060SN/A} 1211060SN/A 1221061SN/Atemplate <class Impl> 1231060SN/Avoid 1241060SN/ASimpleRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 1251060SN/A{ 1261060SN/A DPRINTF(Rename, "Rename: Setting time buffer pointer.\n"); 1271060SN/A timeBuffer = tb_ptr; 1281060SN/A 1291060SN/A // Setup wire to read information from time buffer, from IEW stage. 1301060SN/A fromIEW = timeBuffer->getWire(-iewToRenameDelay); 1311060SN/A 1321060SN/A // Setup wire to read infromation from time buffer, from commit stage. 1331060SN/A fromCommit = timeBuffer->getWire(-commitToRenameDelay); 1341060SN/A 1351060SN/A // Setup wire to write information to previous stages. 1361060SN/A toDecode = timeBuffer->getWire(0); 1371060SN/A} 1381060SN/A 1391061SN/Atemplate <class Impl> 1401060SN/Avoid 1411060SN/ASimpleRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr) 1421060SN/A{ 1431060SN/A DPRINTF(Rename, "Rename: Setting rename queue pointer.\n"); 1441060SN/A renameQueue = rq_ptr; 1451060SN/A 1461060SN/A // Setup wire to write information to future stages. 1471060SN/A toIEW = renameQueue->getWire(0); 1481060SN/A} 1491060SN/A 1501061SN/Atemplate <class Impl> 1511060SN/Avoid 1521060SN/ASimpleRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr) 1531060SN/A{ 1541060SN/A DPRINTF(Rename, "Rename: Setting decode queue pointer.\n"); 1551060SN/A decodeQueue = dq_ptr; 1561060SN/A 1571060SN/A // Setup wire to get information from decode. 1581060SN/A fromDecode = decodeQueue->getWire(-decodeToRenameDelay); 1591060SN/A} 1601060SN/A 1611061SN/Atemplate <class Impl> 1621060SN/Avoid 1631060SN/ASimpleRename<Impl>::setRenameMap(RenameMap *rm_ptr) 1641060SN/A{ 1651060SN/A DPRINTF(Rename, "Rename: Setting rename map pointer.\n"); 1661060SN/A renameMap = rm_ptr; 1671060SN/A} 1681060SN/A 1691061SN/Atemplate <class Impl> 1701060SN/Avoid 1711060SN/ASimpleRename<Impl>::setFreeList(FreeList *fl_ptr) 1721060SN/A{ 1731060SN/A DPRINTF(Rename, "Rename: Setting free list pointer.\n"); 1741060SN/A freeList = fl_ptr; 1751060SN/A} 1761060SN/A 1771061SN/Atemplate <class Impl> 1781060SN/Avoid 1791060SN/ASimpleRename<Impl>::dumpHistory() 1801060SN/A{ 1811060SN/A typename list<RenameHistory>::iterator buf_it = historyBuffer.begin(); 1821060SN/A 1831060SN/A while (buf_it != historyBuffer.end()) 1841060SN/A { 1851060SN/A cprintf("Seq num: %i\nArch reg: %i New phys reg: %i Old phys " 1861060SN/A "reg: %i\n", (*buf_it).instSeqNum, (int)(*buf_it).archReg, 1871060SN/A (int)(*buf_it).newPhysReg, (int)(*buf_it).prevPhysReg); 1881060SN/A 1891060SN/A buf_it++; 1901060SN/A } 1911060SN/A} 1921060SN/A 1931061SN/Atemplate <class Impl> 1941060SN/Avoid 1951060SN/ASimpleRename<Impl>::block() 1961060SN/A{ 1971060SN/A DPRINTF(Rename, "Rename: Blocking.\n"); 1981060SN/A // Set status to Blocked. 1991060SN/A _status = Blocked; 2001060SN/A 2011060SN/A // Add the current inputs onto the skid buffer, so they can be 2021060SN/A // reprocessed when this stage unblocks. 2031060SN/A skidBuffer.push(*fromDecode); 2041060SN/A 2051060SN/A // Note that this stage only signals previous stages to stall when 2061060SN/A // it is the cause of the stall originates at this stage. Otherwise 2071060SN/A // the previous stages are expected to check all possible stall signals. 2081060SN/A} 2091060SN/A 2101061SN/Atemplate <class Impl> 2111060SN/Ainline void 2121060SN/ASimpleRename<Impl>::unblock() 2131060SN/A{ 2141061SN/A DPRINTF(Rename, "Rename: Read instructions out of skid buffer this " 2151061SN/A "cycle.\n"); 2161060SN/A // Remove the now processed instructions from the skid buffer. 2171060SN/A skidBuffer.pop(); 2181060SN/A 2191060SN/A // If there's still information in the skid buffer, then 2201060SN/A // continue to tell previous stages to stall. They will be 2211060SN/A // able to restart once the skid buffer is empty. 2221060SN/A if (!skidBuffer.empty()) { 2231062SN/A toDecode->renameInfo.stall = true; 2241060SN/A } else { 2251060SN/A DPRINTF(Rename, "Rename: Done unblocking.\n"); 2261060SN/A _status = Running; 2271060SN/A } 2281060SN/A} 2291060SN/A 2301061SN/Atemplate <class Impl> 2311060SN/Avoid 2321060SN/ASimpleRename<Impl>::doSquash() 2331060SN/A{ 2341060SN/A typename list<RenameHistory>::iterator hb_it = historyBuffer.begin(); 2351060SN/A 2361060SN/A InstSeqNum squashed_seq_num = fromCommit->commitInfo.doneSeqNum; 2371060SN/A 2381858SN/A#if FULL_SYSTEM 2391060SN/A assert(!historyBuffer.empty()); 2401060SN/A#else 2411060SN/A // After a syscall squashes everything, the history buffer may be empty 2421060SN/A // but the ROB may still be squashing instructions. 2431060SN/A if (historyBuffer.empty()) { 2441060SN/A return; 2451060SN/A } 2461060SN/A#endif // FULL_SYSTEM 2471060SN/A 2481060SN/A // Go through the most recent instructions, undoing the mappings 2491060SN/A // they did and freeing up the registers. 2501060SN/A while ((*hb_it).instSeqNum > squashed_seq_num) 2511060SN/A { 2521062SN/A assert(hb_it != historyBuffer.end()); 2531062SN/A 2541060SN/A DPRINTF(Rename, "Rename: Removing history entry with sequence " 2551060SN/A "number %i.\n", (*hb_it).instSeqNum); 2561060SN/A 2571060SN/A // If it's not simply a place holder, then add the registers. 2581060SN/A if (!(*hb_it).placeHolder) { 2591060SN/A // Tell the rename map to set the architected register to the 2601060SN/A // previous physical register that it was renamed to. 2611060SN/A renameMap->setEntry(hb_it->archReg, hb_it->prevPhysReg); 2621060SN/A 2631060SN/A // Put the renamed physical register back on the free list. 2641060SN/A freeList->addReg(hb_it->newPhysReg); 2651062SN/A 2661062SN/A ++renameValidUndoneMaps; 2671060SN/A } 2681060SN/A 2691061SN/A historyBuffer.erase(hb_it++); 2701061SN/A 2711062SN/A ++renameUndoneMaps; 2721060SN/A } 2731060SN/A} 2741060SN/A 2751061SN/Atemplate <class Impl> 2761060SN/Avoid 2771060SN/ASimpleRename<Impl>::squash() 2781060SN/A{ 2791060SN/A DPRINTF(Rename, "Rename: Squashing instructions.\n"); 2801060SN/A // Set the status to Squashing. 2811060SN/A _status = Squashing; 2821060SN/A 2831061SN/A numInst = 0; 2841061SN/A 2851060SN/A // Clear the skid buffer in case it has any data in it. 2861060SN/A while (!skidBuffer.empty()) 2871060SN/A { 2881060SN/A skidBuffer.pop(); 2891060SN/A } 2901060SN/A 2911060SN/A doSquash(); 2921060SN/A} 2931060SN/A 2941060SN/Atemplate<class Impl> 2951060SN/Avoid 2961060SN/ASimpleRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num) 2971060SN/A{ 2981060SN/A DPRINTF(Rename, "Rename: Removing a committed instruction from the " 2991061SN/A "history buffer, until sequence number %lli.\n", inst_seq_num); 3001060SN/A typename list<RenameHistory>::iterator hb_it = historyBuffer.end(); 3011060SN/A 3021061SN/A --hb_it; 3031060SN/A 3041060SN/A if (hb_it->instSeqNum > inst_seq_num) { 3051060SN/A DPRINTF(Rename, "Rename: Old sequence number encountered. Ensure " 3061060SN/A "that a syscall happened recently.\n"); 3071060SN/A return; 3081060SN/A } 3091060SN/A 3101061SN/A while ((*hb_it).instSeqNum != inst_seq_num) 3111060SN/A { 3121060SN/A // Make sure we haven't gone off the end of the list. 3131060SN/A assert(hb_it != historyBuffer.end()); 3141060SN/A 3151060SN/A // In theory instructions at the end of the history buffer 3161060SN/A // should be older than the instruction being removed, which 3171060SN/A // means they will have a lower sequence number. Also the 3181060SN/A // instruction being removed from the history really should 3191060SN/A // be the last instruction in the list, as it is the instruction 3201060SN/A // that was just committed that is being removed. 3211060SN/A assert(hb_it->instSeqNum < inst_seq_num); 3221061SN/A DPRINTF(Rename, "Rename: Freeing up older rename of reg %i, sequence" 3231061SN/A " number %i.\n", 3241061SN/A (*hb_it).prevPhysReg, (*hb_it).instSeqNum); 3251061SN/A 3261061SN/A if (!(*hb_it).placeHolder) { 3271061SN/A freeList->addReg((*hb_it).prevPhysReg); 3281062SN/A ++renameCommittedMaps; 3291061SN/A } 3301061SN/A 3311061SN/A historyBuffer.erase(hb_it--); 3321060SN/A } 3331060SN/A 3341062SN/A // Finally free up the previous register of the finished instruction 3351061SN/A // itself. 3361060SN/A if (!(*hb_it).placeHolder) { 3371060SN/A freeList->addReg(hb_it->prevPhysReg); 3381062SN/A ++renameCommittedMaps; 3391060SN/A } 3401060SN/A 3411060SN/A historyBuffer.erase(hb_it); 3421060SN/A} 3431060SN/A 3441061SN/Atemplate <class Impl> 3451061SN/Ainline void 3461061SN/ASimpleRename<Impl>::renameSrcRegs(DynInstPtr &inst) 3471061SN/A{ 3481061SN/A unsigned num_src_regs = inst->numSrcRegs(); 3491061SN/A 3501061SN/A // Get the architectual register numbers from the source and 3511061SN/A // destination operands, and redirect them to the right register. 3521061SN/A // Will need to mark dependencies though. 3531061SN/A for (int src_idx = 0; src_idx < num_src_regs; src_idx++) 3541061SN/A { 3551061SN/A RegIndex src_reg = inst->srcRegIdx(src_idx); 3561061SN/A 3571061SN/A // Look up the source registers to get the phys. register they've 3581061SN/A // been renamed to, and set the sources to those registers. 3591062SN/A PhysRegIndex renamed_reg = renameMap->lookup(src_reg); 3601061SN/A 3611061SN/A DPRINTF(Rename, "Rename: Looking up arch reg %i, got " 3621061SN/A "physical reg %i.\n", (int)src_reg, (int)renamed_reg); 3631061SN/A 3641061SN/A inst->renameSrcReg(src_idx, renamed_reg); 3651061SN/A 3661061SN/A // Either incorporate it into the info passed back, 3671061SN/A // or make another function call to see if that register is 3681061SN/A // ready or not. 3691061SN/A if (renameMap->isReady(renamed_reg)) { 3701061SN/A DPRINTF(Rename, "Rename: Register is ready.\n"); 3711061SN/A 3721061SN/A inst->markSrcRegReady(src_idx); 3731061SN/A } 3741062SN/A 3751062SN/A ++renameRenameLookups; 3761061SN/A } 3771061SN/A} 3781061SN/A 3791061SN/Atemplate <class Impl> 3801061SN/Ainline void 3811061SN/ASimpleRename<Impl>::renameDestRegs(DynInstPtr &inst) 3821061SN/A{ 3831061SN/A typename SimpleRenameMap::RenameInfo rename_result; 3841061SN/A 3851061SN/A unsigned num_dest_regs = inst->numDestRegs(); 3861061SN/A 3871061SN/A // If it's an instruction with no destination registers, then put 3881061SN/A // a placeholder within the history buffer. It might be better 3891061SN/A // to not put it in the history buffer at all (other than branches, 3901061SN/A // which always need at least a place holder), and differentiate 3911061SN/A // between instructions with and without destination registers 3921061SN/A // when getting from commit the instructions that committed. 3931061SN/A if (num_dest_regs == 0) { 3941061SN/A RenameHistory hb_entry(inst->seqNum); 3951061SN/A 3961061SN/A historyBuffer.push_front(hb_entry); 3971061SN/A 3981061SN/A DPRINTF(Rename, "Rename: Adding placeholder instruction to " 3991061SN/A "history buffer, sequence number %lli.\n", 4001061SN/A inst->seqNum); 4011062SN/A 4021062SN/A ++renameHBPlaceHolders; 4031062SN/A } else { 4041062SN/A 4051062SN/A // Rename the destination registers. 4061062SN/A for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++) 4071062SN/A { 4081062SN/A RegIndex dest_reg = inst->destRegIdx(dest_idx); 4091062SN/A 4101062SN/A // Get the physical register that the destination will be 4111062SN/A // renamed to. 4121062SN/A rename_result = renameMap->rename(dest_reg); 4131062SN/A 4141062SN/A DPRINTF(Rename, "Rename: Renaming arch reg %i to physical " 4151062SN/A "reg %i.\n", (int)dest_reg, 4161062SN/A (int)rename_result.first); 4171062SN/A 4181062SN/A // Record the rename information so that a history can be kept. 4191062SN/A RenameHistory hb_entry(inst->seqNum, dest_reg, 4201062SN/A rename_result.first, 4211062SN/A rename_result.second); 4221062SN/A 4231062SN/A historyBuffer.push_front(hb_entry); 4241062SN/A 4251062SN/A DPRINTF(Rename, "Rename: Adding instruction to history buffer, " 4261062SN/A "sequence number %lli.\n", 4271062SN/A (*historyBuffer.begin()).instSeqNum); 4281062SN/A 4291062SN/A // Tell the instruction to rename the appropriate destination 4301062SN/A // register (dest_idx) to the new physical register 4311062SN/A // (rename_result.first), and record the previous physical 4321062SN/A // register that the same logical register was renamed to 4331062SN/A // (rename_result.second). 4341062SN/A inst->renameDestReg(dest_idx, 4351062SN/A rename_result.first, 4361062SN/A rename_result.second); 4371062SN/A 4381062SN/A ++renameRenamedOperands; 4391062SN/A } 4401061SN/A } 4411061SN/A} 4421061SN/A 4431061SN/Atemplate <class Impl> 4441061SN/Ainline int 4451061SN/ASimpleRename<Impl>::calcFreeROBEntries() 4461061SN/A{ 4471061SN/A return fromCommit->commitInfo.freeROBEntries - 4481061SN/A renameWidth * iewToRenameDelay; 4491061SN/A} 4501061SN/A 4511061SN/Atemplate <class Impl> 4521061SN/Ainline int 4531061SN/ASimpleRename<Impl>::calcFreeIQEntries() 4541061SN/A{ 4551061SN/A return fromIEW->iewInfo.freeIQEntries - renameWidth * iewToRenameDelay; 4561061SN/A} 4571061SN/A 4581060SN/Atemplate<class Impl> 4591060SN/Avoid 4601060SN/ASimpleRename<Impl>::tick() 4611060SN/A{ 4621060SN/A // Rename will need to try to rename as many instructions as it 4631060SN/A // has bandwidth, unless it is blocked. 4641060SN/A 4651060SN/A // Check if _status is BarrierStall. If so, then check if the number 4661060SN/A // of free ROB entries is equal to the number of total ROB entries. 4671060SN/A // Once equal then wake this stage up. Set status to unblocking maybe. 4681060SN/A 4691060SN/A if (_status != Blocked && _status != Squashing) { 4701060SN/A DPRINTF(Rename, "Rename: Status is not blocked, will attempt to " 4711060SN/A "run stage.\n"); 4721060SN/A // Make sure that the skid buffer has something in it if the 4731060SN/A // status is unblocking. 4741060SN/A assert(_status == Unblocking ? !skidBuffer.empty() : 1); 4751060SN/A 4761060SN/A rename(); 4771060SN/A 4781060SN/A // If the status was unblocking, then instructions from the skid 4791060SN/A // buffer were used. Remove those instructions and handle 4801060SN/A // the rest of unblocking. 4811060SN/A if (_status == Unblocking) { 4821062SN/A ++renameUnblockCycles; 4831062SN/A 4841061SN/A if (fromDecode->size > 0) { 4851061SN/A // Add the current inputs onto the skid buffer, so they can be 4861061SN/A // reprocessed when this stage unblocks. 4871061SN/A skidBuffer.push(*fromDecode); 4881061SN/A } 4891061SN/A 4901060SN/A unblock(); 4911060SN/A } 4921060SN/A } else if (_status == Blocked) { 4931062SN/A ++renameBlockCycles; 4941062SN/A 4951060SN/A // If stage is blocked and still receiving valid instructions, 4961060SN/A // make sure to store them in the skid buffer. 4971061SN/A if (fromDecode->size > 0) { 4981060SN/A 4991060SN/A block(); 5001060SN/A 5011060SN/A // Continue to tell previous stage to stall. 5021060SN/A toDecode->renameInfo.stall = true; 5031060SN/A } 5041060SN/A 5051060SN/A if (!fromIEW->iewInfo.stall && 5061060SN/A !fromCommit->commitInfo.stall && 5071061SN/A calcFreeROBEntries() > 0 && 5081061SN/A calcFreeIQEntries() > 0 && 5091061SN/A renameMap->numFreeEntries() > 0) { 5101060SN/A 5111060SN/A // Need to be sure to check all blocking conditions above. 5121060SN/A // If they have cleared, then start unblocking. 5131060SN/A DPRINTF(Rename, "Rename: Stall signals cleared, going to " 5141060SN/A "unblock.\n"); 5151060SN/A _status = Unblocking; 5161060SN/A 5171060SN/A // Continue to tell previous stage to block until this stage 5181060SN/A // is done unblocking. 5191060SN/A toDecode->renameInfo.stall = true; 5201060SN/A } else { 5211060SN/A // Otherwise no conditions have changed. Tell previous 5221060SN/A // stage to continue blocking. 5231060SN/A toDecode->renameInfo.stall = true; 5241060SN/A } 5251060SN/A 5261060SN/A if (fromCommit->commitInfo.squash || 5271060SN/A fromCommit->commitInfo.robSquashing) { 5281060SN/A squash(); 5291060SN/A return; 5301060SN/A } 5311060SN/A } else if (_status == Squashing) { 5321062SN/A ++renameSquashCycles; 5331062SN/A 5341060SN/A if (fromCommit->commitInfo.squash) { 5351060SN/A squash(); 5361060SN/A } else if (!fromCommit->commitInfo.squash && 5371060SN/A !fromCommit->commitInfo.robSquashing) { 5381060SN/A 5391060SN/A DPRINTF(Rename, "Rename: Done squashing, going to running.\n"); 5401060SN/A _status = Running; 5411684SN/A rename(); 5421060SN/A } else { 5431060SN/A doSquash(); 5441060SN/A } 5451060SN/A } 5461060SN/A 5471060SN/A // Ugly code, revamp all of the tick() functions eventually. 5481060SN/A if (fromCommit->commitInfo.doneSeqNum != 0 && _status != Squashing) { 5491858SN/A#if !FULL_SYSTEM 5501062SN/A if (!fromCommit->commitInfo.squash) { 5511062SN/A removeFromHistory(fromCommit->commitInfo.doneSeqNum); 5521062SN/A } 5531062SN/A#else 5541060SN/A removeFromHistory(fromCommit->commitInfo.doneSeqNum); 5551062SN/A#endif 5561060SN/A } 5571060SN/A 5581060SN/A} 5591060SN/A 5601060SN/Atemplate<class Impl> 5611060SN/Avoid 5621060SN/ASimpleRename<Impl>::rename() 5631060SN/A{ 5641060SN/A // Check if any of the stages ahead of rename are telling rename 5651060SN/A // to squash. The squash() function will also take care of fixing up 5661060SN/A // the rename map and the free list. 5671060SN/A if (fromCommit->commitInfo.squash || 5681060SN/A fromCommit->commitInfo.robSquashing) { 5691061SN/A DPRINTF(Rename, "Rename: Receiving signal from Commit to squash.\n"); 5701060SN/A squash(); 5711060SN/A return; 5721060SN/A } 5731060SN/A 5741060SN/A // Check if time buffer is telling this stage to stall. 5751060SN/A if (fromIEW->iewInfo.stall || 5761060SN/A fromCommit->commitInfo.stall) { 5771060SN/A DPRINTF(Rename, "Rename: Receiving signal from IEW/Commit to " 5781060SN/A "stall.\n"); 5791060SN/A block(); 5801060SN/A return; 5811060SN/A } 5821060SN/A 5831060SN/A // Check if the current status is squashing. If so, set its status 5841060SN/A // to running and resume execution the next cycle. 5851060SN/A if (_status == Squashing) { 5861060SN/A DPRINTF(Rename, "Rename: Done squashing.\n"); 5871060SN/A _status = Running; 5881060SN/A return; 5891060SN/A } 5901060SN/A 5911060SN/A // Check the decode queue to see if instructions are available. 5921060SN/A // If there are no available instructions to rename, then do nothing. 5931060SN/A // Or, if the stage is currently unblocking, then go ahead and run it. 5941061SN/A if (fromDecode->size == 0 && _status != Unblocking) { 5951060SN/A DPRINTF(Rename, "Rename: Nothing to do, breaking out early.\n"); 5961060SN/A // Should I change status to idle? 5971060SN/A return; 5981060SN/A } 5991060SN/A 6001061SN/A //////////////////////////////////// 6011061SN/A // Actual rename part. 6021061SN/A //////////////////////////////////// 6031060SN/A 6041061SN/A DynInstPtr inst; 6051060SN/A 6061061SN/A // If we're unblocking, then we may be in the middle of an instruction 6071061SN/A // group. Subtract off numInst to get the proper number of instructions 6081061SN/A // left. 6091061SN/A int insts_available = _status == Unblocking ? 6101061SN/A skidBuffer.front().size - numInst : 6111061SN/A fromDecode->size; 6121060SN/A 6131061SN/A bool block_this_cycle = false; 6141060SN/A 6151060SN/A // Will have to do a different calculation for the number of free 6161060SN/A // entries. Number of free entries recorded on this cycle - 6171060SN/A // renameWidth * renameToDecodeDelay 6181061SN/A int free_rob_entries = calcFreeROBEntries(); 6191061SN/A int free_iq_entries = calcFreeIQEntries(); 6201061SN/A int min_iq_rob = min(free_rob_entries, free_iq_entries); 6211061SN/A 6221061SN/A unsigned to_iew_index = 0; 6231060SN/A 6241060SN/A // Check if there's any space left. 6251061SN/A if (min_iq_rob <= 0) { 6261060SN/A DPRINTF(Rename, "Rename: Blocking due to no free ROB or IQ " 6271060SN/A "entries.\n" 6281060SN/A "Rename: ROB has %d free entries.\n" 6291060SN/A "Rename: IQ has %d free entries.\n", 6301060SN/A free_rob_entries, 6311060SN/A free_iq_entries); 6321060SN/A block(); 6331060SN/A // Tell previous stage to stall. 6341060SN/A toDecode->renameInfo.stall = true; 6351060SN/A 6361062SN/A if (free_rob_entries <= 0) { 6371062SN/A ++renameROBFullEvents; 6381062SN/A } else { 6391062SN/A ++renameIQFullEvents; 6401062SN/A } 6411062SN/A 6421060SN/A return; 6431061SN/A } else if (min_iq_rob < insts_available) { 6441061SN/A DPRINTF(Rename, "Rename: Will have to block this cycle. Only " 6451061SN/A "%i insts can be renamed due to IQ/ROB limits.\n", 6461061SN/A min_iq_rob); 6471061SN/A 6481061SN/A insts_available = min_iq_rob; 6491061SN/A 6501061SN/A block_this_cycle = true; 6511062SN/A 6521062SN/A if (free_rob_entries < free_iq_entries) { 6531062SN/A ++renameROBFullEvents; 6541062SN/A } else { 6551062SN/A ++renameIQFullEvents; 6561062SN/A } 6571060SN/A } 6581060SN/A 6591061SN/A while (insts_available > 0) { 6601060SN/A DPRINTF(Rename, "Rename: Sending instructions to iew.\n"); 6611060SN/A 6621060SN/A // Get the next instruction either from the skid buffer or the 6631060SN/A // decode queue. 6641061SN/A inst = _status == Unblocking ? skidBuffer.front().insts[numInst] : 6651061SN/A fromDecode->insts[numInst]; 6661061SN/A 6671061SN/A if (inst->isSquashed()) { 6681061SN/A DPRINTF(Rename, "Rename: instruction %i with PC %#x is " 6691061SN/A "squashed, skipping.\n", 6701061SN/A inst->seqNum, inst->readPC()); 6711061SN/A 6721061SN/A // Go to the next instruction. 6731061SN/A ++numInst; 6741061SN/A 6751062SN/A ++renameSquashedInsts; 6761062SN/A 6771061SN/A // Decrement how many instructions are available. 6781061SN/A --insts_available; 6791061SN/A 6801061SN/A continue; 6811061SN/A } 6821060SN/A 6831060SN/A DPRINTF(Rename, "Rename: Processing instruction %i with PC %#x.\n", 6841061SN/A inst->seqNum, inst->readPC()); 6851060SN/A 6861060SN/A // If it's a trap instruction, then it needs to wait here within 6871060SN/A // rename until the ROB is empty. Needs a way to detect that the 6881060SN/A // ROB is empty. Maybe an event? 6891060SN/A // Would be nice if it could be avoided putting this into a 6901060SN/A // specific stage and instead just put it into the AlphaFullCPU. 6911060SN/A // Might not really be feasible though... 6921060SN/A // (EXCB, TRAPB) 6931060SN/A if (inst->isSerializing()) { 6941060SN/A panic("Rename: Serializing instruction encountered.\n"); 6951060SN/A DPRINTF(Rename, "Rename: Serializing instruction " 6961060SN/A "encountered.\n"); 6971060SN/A 6981060SN/A // Change status over to BarrierStall so that other stages know 6991060SN/A // what this is blocked on. 7001060SN/A _status = BarrierStall; 7011060SN/A 7021061SN/A block_this_cycle = true; 7031060SN/A 7041060SN/A break; 7051060SN/A } 7061060SN/A 7071061SN/A // Check here to make sure there are enough destination registers 7081061SN/A // to rename to. Otherwise block. 7091061SN/A if (renameMap->numFreeEntries() < inst->numDestRegs()) 7101061SN/A { 7111061SN/A DPRINTF(Rename, "Rename: Blocking due to lack of free " 7121061SN/A "physical registers to rename to.\n"); 7131061SN/A // Need some sort of event based on a register being freed. 7141060SN/A 7151061SN/A block_this_cycle = true; 7161060SN/A 7171062SN/A ++renameFullRegistersEvents; 7181062SN/A 7191060SN/A break; 7201060SN/A } 7211060SN/A 7221061SN/A renameSrcRegs(inst); 7231060SN/A 7241061SN/A renameDestRegs(inst); 7251060SN/A 7261060SN/A // Put instruction in rename queue. 7271061SN/A toIEW->insts[to_iew_index] = inst; 7281061SN/A ++(toIEW->size); 7291060SN/A 7301060SN/A // Decrease the number of free ROB and IQ entries. 7311060SN/A --free_rob_entries; 7321060SN/A --free_iq_entries; 7331060SN/A 7341060SN/A // Increment which instruction we're on. 7351061SN/A ++to_iew_index; 7361061SN/A ++numInst; 7371060SN/A 7381062SN/A ++renameRenamedInsts; 7391062SN/A 7401061SN/A // Decrement how many instructions are available. 7411061SN/A --insts_available; 7421060SN/A } 7431060SN/A 7441061SN/A // Check if there's any instructions left that haven't yet been renamed. 7451061SN/A // If so then block. 7461061SN/A if (block_this_cycle) { 7471061SN/A block(); 7481061SN/A 7491061SN/A toDecode->renameInfo.stall = true; 7501061SN/A } else { 7511061SN/A // If we had a successful rename and didn't have to exit early, then 7521061SN/A // reset numInst so it will refer to the correct instruction on next 7531061SN/A // run. 7541061SN/A numInst = 0; 7551061SN/A } 7561060SN/A} 757