rename_impl.hh revision 1858
17732SAli.Saidi@ARM.com/* 27732SAli.Saidi@ARM.com * Copyright (c) 2004-2005 The Regents of The University of Michigan 37732SAli.Saidi@ARM.com * All rights reserved. 47732SAli.Saidi@ARM.com * 57732SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 67732SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are 77732SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright 87732SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer; 97732SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright 107732SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the 117732SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 127732SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its 137732SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from 147732SAli.Saidi@ARM.com * this software without specific prior written permission. 157732SAli.Saidi@ARM.com * 167732SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177732SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187732SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197732SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207732SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217732SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227732SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237732SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247732SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257732SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267732SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277732SAli.Saidi@ARM.com */ 287732SAli.Saidi@ARM.com 297732SAli.Saidi@ARM.com#include <list> 307732SAli.Saidi@ARM.com 317732SAli.Saidi@ARM.com#include "config/full_system.hh" 327732SAli.Saidi@ARM.com#include "cpu/o3/rename.hh" 337732SAli.Saidi@ARM.com 347732SAli.Saidi@ARM.comtemplate <class Impl> 357732SAli.Saidi@ARM.comSimpleRename<Impl>::SimpleRename(Params ¶ms) 367732SAli.Saidi@ARM.com : iewToRenameDelay(params.iewToRenameDelay), 377732SAli.Saidi@ARM.com decodeToRenameDelay(params.decodeToRenameDelay), 387732SAli.Saidi@ARM.com commitToRenameDelay(params.commitToRenameDelay), 397732SAli.Saidi@ARM.com renameWidth(params.renameWidth), 407732SAli.Saidi@ARM.com commitWidth(params.commitWidth), 417732SAli.Saidi@ARM.com numInst(0) 428204SAli.Saidi@ARM.com{ 438204SAli.Saidi@ARM.com _status = Idle; 448204SAli.Saidi@ARM.com} 458204SAli.Saidi@ARM.com 468204SAli.Saidi@ARM.comtemplate <class Impl> 478204SAli.Saidi@ARM.comvoid 488204SAli.Saidi@ARM.comSimpleRename<Impl>::regStats() 498204SAli.Saidi@ARM.com{ 508204SAli.Saidi@ARM.com renameSquashCycles 518204SAli.Saidi@ARM.com .name(name() + ".renameSquashCycles") 528204SAli.Saidi@ARM.com .desc("Number of cycles rename is squashing") 538204SAli.Saidi@ARM.com .prereq(renameSquashCycles); 548204SAli.Saidi@ARM.com renameIdleCycles 557732SAli.Saidi@ARM.com .name(name() + ".renameIdleCycles") 567732SAli.Saidi@ARM.com .desc("Number of cycles rename is idle") 577732SAli.Saidi@ARM.com .prereq(renameIdleCycles); 587732SAli.Saidi@ARM.com renameBlockCycles 597732SAli.Saidi@ARM.com .name(name() + ".renameBlockCycles") 607732SAli.Saidi@ARM.com .desc("Number of cycles rename is blocking") 617732SAli.Saidi@ARM.com .prereq(renameBlockCycles); 627732SAli.Saidi@ARM.com renameUnblockCycles 637732SAli.Saidi@ARM.com .name(name() + ".renameUnblockCycles") 647732SAli.Saidi@ARM.com .desc("Number of cycles rename is unblocking") 657732SAli.Saidi@ARM.com .prereq(renameUnblockCycles); 667732SAli.Saidi@ARM.com renameRenamedInsts 677732SAli.Saidi@ARM.com .name(name() + ".renameRenamedInsts") 687732SAli.Saidi@ARM.com .desc("Number of instructions processed by rename") 697732SAli.Saidi@ARM.com .prereq(renameRenamedInsts); 707732SAli.Saidi@ARM.com renameSquashedInsts 718204SAli.Saidi@ARM.com .name(name() + ".renameSquashedInsts") 727732SAli.Saidi@ARM.com .desc("Number of squashed instructions processed by rename") 737732SAli.Saidi@ARM.com .prereq(renameSquashedInsts); 747732SAli.Saidi@ARM.com renameROBFullEvents 757732SAli.Saidi@ARM.com .name(name() + ".renameROBFullEvents") 767732SAli.Saidi@ARM.com .desc("Number of times rename has considered the ROB 'full'") 777732SAli.Saidi@ARM.com .prereq(renameROBFullEvents); 787732SAli.Saidi@ARM.com renameIQFullEvents 797732SAli.Saidi@ARM.com .name(name() + ".renameIQFullEvents") 808142SAli.Saidi@ARM.com .desc("Number of times rename has considered the IQ 'full'") 817732SAli.Saidi@ARM.com .prereq(renameIQFullEvents); 827732SAli.Saidi@ARM.com renameFullRegistersEvents 837732SAli.Saidi@ARM.com .name(name() + ".renameFullRegisterEvents") 848204SAli.Saidi@ARM.com .desc("Number of times there has been no free registers") 857732SAli.Saidi@ARM.com .prereq(renameFullRegistersEvents); 867732SAli.Saidi@ARM.com renameRenamedOperands 877732SAli.Saidi@ARM.com .name(name() + ".renameRenamedOperands") 887732SAli.Saidi@ARM.com .desc("Number of destination operands rename has renamed") 897732SAli.Saidi@ARM.com .prereq(renameRenamedOperands); 907732SAli.Saidi@ARM.com renameRenameLookups 917732SAli.Saidi@ARM.com .name(name() + ".renameRenameLookups") 927732SAli.Saidi@ARM.com .desc("Number of register rename lookups that rename has made") 937732SAli.Saidi@ARM.com .prereq(renameRenameLookups); 948142SAli.Saidi@ARM.com renameHBPlaceHolders 957732SAli.Saidi@ARM.com .name(name() + ".renameHBPlaceHolders") 967732SAli.Saidi@ARM.com .desc("Number of place holders added to the history buffer") 977732SAli.Saidi@ARM.com .prereq(renameHBPlaceHolders); 988204SAli.Saidi@ARM.com renameCommittedMaps 997732SAli.Saidi@ARM.com .name(name() + ".renameCommittedMaps") 1007732SAli.Saidi@ARM.com .desc("Number of HB maps that are committed") 1017732SAli.Saidi@ARM.com .prereq(renameCommittedMaps); 1027732SAli.Saidi@ARM.com renameUndoneMaps 1037732SAli.Saidi@ARM.com .name(name() + ".renameUndoneMaps") 1047732SAli.Saidi@ARM.com .desc("Number of HB maps that are undone due to squashing") 1057732SAli.Saidi@ARM.com .prereq(renameUndoneMaps); 1067732SAli.Saidi@ARM.com renameValidUndoneMaps 1077732SAli.Saidi@ARM.com .name(name() + ".renameValidUndoneMaps") 1088142SAli.Saidi@ARM.com .desc("Number of HB maps that are undone, and are not place holders") 1097732SAli.Saidi@ARM.com .prereq(renameValidUndoneMaps); 1107732SAli.Saidi@ARM.com} 1117732SAli.Saidi@ARM.com 1128204SAli.Saidi@ARM.comtemplate <class Impl> 1138204SAli.Saidi@ARM.comvoid 1148204SAli.Saidi@ARM.comSimpleRename<Impl>::setCPU(FullCPU *cpu_ptr) 1157732SAli.Saidi@ARM.com{ 1167732SAli.Saidi@ARM.com DPRINTF(Rename, "Rename: Setting CPU pointer.\n"); 1177732SAli.Saidi@ARM.com cpu = cpu_ptr; 1187732SAli.Saidi@ARM.com} 1197732SAli.Saidi@ARM.com 1207732SAli.Saidi@ARM.comtemplate <class Impl> 1217732SAli.Saidi@ARM.comvoid 1227732SAli.Saidi@ARM.comSimpleRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 1237732SAli.Saidi@ARM.com{ 1247732SAli.Saidi@ARM.com DPRINTF(Rename, "Rename: Setting time buffer pointer.\n"); 1257732SAli.Saidi@ARM.com timeBuffer = tb_ptr; 1268204SAli.Saidi@ARM.com 1278204SAli.Saidi@ARM.com // Setup wire to read information from time buffer, from IEW stage. 1288204SAli.Saidi@ARM.com fromIEW = timeBuffer->getWire(-iewToRenameDelay); 1298204SAli.Saidi@ARM.com 1308204SAli.Saidi@ARM.com // Setup wire to read infromation from time buffer, from commit stage. 1318204SAli.Saidi@ARM.com fromCommit = timeBuffer->getWire(-commitToRenameDelay); 1327732SAli.Saidi@ARM.com 1338204SAli.Saidi@ARM.com // Setup wire to write information to previous stages. 1347732SAli.Saidi@ARM.com toDecode = timeBuffer->getWire(0); 1357732SAli.Saidi@ARM.com} 1367732SAli.Saidi@ARM.com 1377732SAli.Saidi@ARM.comtemplate <class Impl> 1387732SAli.Saidi@ARM.comvoid 1397732SAli.Saidi@ARM.comSimpleRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr) 1408204SAli.Saidi@ARM.com{ 1418204SAli.Saidi@ARM.com DPRINTF(Rename, "Rename: Setting rename queue pointer.\n"); 1428204SAli.Saidi@ARM.com renameQueue = rq_ptr; 1438204SAli.Saidi@ARM.com 1447732SAli.Saidi@ARM.com // Setup wire to write information to future stages. 1458204SAli.Saidi@ARM.com toIEW = renameQueue->getWire(0); 1468204SAli.Saidi@ARM.com} 1478204SAli.Saidi@ARM.com 1487732SAli.Saidi@ARM.comtemplate <class Impl> 1497732SAli.Saidi@ARM.comvoid 1507732SAli.Saidi@ARM.comSimpleRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr) 1517732SAli.Saidi@ARM.com{ 1527732SAli.Saidi@ARM.com DPRINTF(Rename, "Rename: Setting decode queue pointer.\n"); 1537732SAli.Saidi@ARM.com decodeQueue = dq_ptr; 1547732SAli.Saidi@ARM.com 1557732SAli.Saidi@ARM.com // Setup wire to get information from decode. 1567732SAli.Saidi@ARM.com fromDecode = decodeQueue->getWire(-decodeToRenameDelay); 1577732SAli.Saidi@ARM.com} 1587732SAli.Saidi@ARM.com 1597732SAli.Saidi@ARM.comtemplate <class Impl> 1607732SAli.Saidi@ARM.comvoid 1617732SAli.Saidi@ARM.comSimpleRename<Impl>::setRenameMap(RenameMap *rm_ptr) 1627732SAli.Saidi@ARM.com{ 1637732SAli.Saidi@ARM.com DPRINTF(Rename, "Rename: Setting rename map pointer.\n"); 1647732SAli.Saidi@ARM.com renameMap = rm_ptr; 1657732SAli.Saidi@ARM.com} 1667732SAli.Saidi@ARM.com 1677732SAli.Saidi@ARM.comtemplate <class Impl> 1687732SAli.Saidi@ARM.comvoid 1697732SAli.Saidi@ARM.comSimpleRename<Impl>::setFreeList(FreeList *fl_ptr) 1707732SAli.Saidi@ARM.com{ 1717732SAli.Saidi@ARM.com DPRINTF(Rename, "Rename: Setting free list pointer.\n"); 1727732SAli.Saidi@ARM.com freeList = fl_ptr; 1737732SAli.Saidi@ARM.com} 1747732SAli.Saidi@ARM.com 1757732SAli.Saidi@ARM.comtemplate <class Impl> 1767732SAli.Saidi@ARM.comvoid 1777732SAli.Saidi@ARM.comSimpleRename<Impl>::dumpHistory() 1787732SAli.Saidi@ARM.com{ 1798204SAli.Saidi@ARM.com typename list<RenameHistory>::iterator buf_it = historyBuffer.begin(); 1808204SAli.Saidi@ARM.com 1818204SAli.Saidi@ARM.com while (buf_it != historyBuffer.end()) 1827732SAli.Saidi@ARM.com { 1838204SAli.Saidi@ARM.com cprintf("Seq num: %i\nArch reg: %i New phys reg: %i Old phys " 1848204SAli.Saidi@ARM.com "reg: %i\n", (*buf_it).instSeqNum, (int)(*buf_it).archReg, 1858204SAli.Saidi@ARM.com (int)(*buf_it).newPhysReg, (int)(*buf_it).prevPhysReg); 1867732SAli.Saidi@ARM.com 1877732SAli.Saidi@ARM.com buf_it++; 1887732SAli.Saidi@ARM.com } 1897732SAli.Saidi@ARM.com} 1907732SAli.Saidi@ARM.com 1917732SAli.Saidi@ARM.comtemplate <class Impl> 1927732SAli.Saidi@ARM.comvoid 1937732SAli.Saidi@ARM.comSimpleRename<Impl>::block() 1947732SAli.Saidi@ARM.com{ 1957732SAli.Saidi@ARM.com DPRINTF(Rename, "Rename: Blocking.\n"); 1967732SAli.Saidi@ARM.com // Set status to Blocked. 1977732SAli.Saidi@ARM.com _status = Blocked; 1987732SAli.Saidi@ARM.com 1997732SAli.Saidi@ARM.com // Add the current inputs onto the skid buffer, so they can be 2007732SAli.Saidi@ARM.com // reprocessed when this stage unblocks. 2017732SAli.Saidi@ARM.com skidBuffer.push(*fromDecode); 2027732SAli.Saidi@ARM.com 2037732SAli.Saidi@ARM.com // Note that this stage only signals previous stages to stall when 2047732SAli.Saidi@ARM.com // it is the cause of the stall originates at this stage. Otherwise 2057732SAli.Saidi@ARM.com // the previous stages are expected to check all possible stall signals. 2067732SAli.Saidi@ARM.com} 2077732SAli.Saidi@ARM.com 2087732SAli.Saidi@ARM.comtemplate <class Impl> 2097732SAli.Saidi@ARM.cominline void 2107732SAli.Saidi@ARM.comSimpleRename<Impl>::unblock() 2117732SAli.Saidi@ARM.com{ 2127732SAli.Saidi@ARM.com DPRINTF(Rename, "Rename: Read instructions out of skid buffer this " 2137732SAli.Saidi@ARM.com "cycle.\n"); 2147732SAli.Saidi@ARM.com // Remove the now processed instructions from the skid buffer. 2157732SAli.Saidi@ARM.com skidBuffer.pop(); 2167732SAli.Saidi@ARM.com 2178204SAli.Saidi@ARM.com // If there's still information in the skid buffer, then 2188204SAli.Saidi@ARM.com // continue to tell previous stages to stall. They will be 2198204SAli.Saidi@ARM.com // able to restart once the skid buffer is empty. 2208204SAli.Saidi@ARM.com if (!skidBuffer.empty()) { 2217732SAli.Saidi@ARM.com toDecode->renameInfo.stall = true; 2228204SAli.Saidi@ARM.com } else { 2237732SAli.Saidi@ARM.com DPRINTF(Rename, "Rename: Done unblocking.\n"); 2247732SAli.Saidi@ARM.com _status = Running; 2257732SAli.Saidi@ARM.com } 2267732SAli.Saidi@ARM.com} 2277732SAli.Saidi@ARM.com 2287732SAli.Saidi@ARM.comtemplate <class Impl> 2298204SAli.Saidi@ARM.comvoid 2308204SAli.Saidi@ARM.comSimpleRename<Impl>::doSquash() 2318204SAli.Saidi@ARM.com{ 2327732SAli.Saidi@ARM.com typename list<RenameHistory>::iterator hb_it = historyBuffer.begin(); 2338204SAli.Saidi@ARM.com 2347732SAli.Saidi@ARM.com InstSeqNum squashed_seq_num = fromCommit->commitInfo.doneSeqNum; 2357732SAli.Saidi@ARM.com 2367732SAli.Saidi@ARM.com#if FULL_SYSTEM 2377732SAli.Saidi@ARM.com assert(!historyBuffer.empty()); 2387732SAli.Saidi@ARM.com#else 2397732SAli.Saidi@ARM.com // After a syscall squashes everything, the history buffer may be empty 2408204SAli.Saidi@ARM.com // but the ROB may still be squashing instructions. 2418204SAli.Saidi@ARM.com if (historyBuffer.empty()) { 2428204SAli.Saidi@ARM.com return; 2437732SAli.Saidi@ARM.com } 2448204SAli.Saidi@ARM.com#endif // FULL_SYSTEM 2457732SAli.Saidi@ARM.com 2467732SAli.Saidi@ARM.com // Go through the most recent instructions, undoing the mappings 2477732SAli.Saidi@ARM.com // they did and freeing up the registers. 2487732SAli.Saidi@ARM.com while ((*hb_it).instSeqNum > squashed_seq_num) 2497732SAli.Saidi@ARM.com { 2507732SAli.Saidi@ARM.com assert(hb_it != historyBuffer.end()); 2518204SAli.Saidi@ARM.com 2528204SAli.Saidi@ARM.com DPRINTF(Rename, "Rename: Removing history entry with sequence " 2538204SAli.Saidi@ARM.com "number %i.\n", (*hb_it).instSeqNum); 2547732SAli.Saidi@ARM.com 2558204SAli.Saidi@ARM.com // If it's not simply a place holder, then add the registers. 2567732SAli.Saidi@ARM.com if (!(*hb_it).placeHolder) { 2577732SAli.Saidi@ARM.com // Tell the rename map to set the architected register to the 2587732SAli.Saidi@ARM.com // previous physical register that it was renamed to. 2597732SAli.Saidi@ARM.com renameMap->setEntry(hb_it->archReg, hb_it->prevPhysReg); 2607732SAli.Saidi@ARM.com 2617732SAli.Saidi@ARM.com // Put the renamed physical register back on the free list. 2627732SAli.Saidi@ARM.com freeList->addReg(hb_it->newPhysReg); 2637732SAli.Saidi@ARM.com 2648204SAli.Saidi@ARM.com ++renameValidUndoneMaps; 2658204SAli.Saidi@ARM.com } 2668204SAli.Saidi@ARM.com 2677732SAli.Saidi@ARM.com historyBuffer.erase(hb_it++); 2687732SAli.Saidi@ARM.com 2697732SAli.Saidi@ARM.com ++renameUndoneMaps; 2707732SAli.Saidi@ARM.com } 2717732SAli.Saidi@ARM.com} 2727732SAli.Saidi@ARM.com 2737732SAli.Saidi@ARM.comtemplate <class Impl> 2747732SAli.Saidi@ARM.comvoid 2757732SAli.Saidi@ARM.comSimpleRename<Impl>::squash() 2767732SAli.Saidi@ARM.com{ 2777732SAli.Saidi@ARM.com DPRINTF(Rename, "Rename: Squashing instructions.\n"); 2787732SAli.Saidi@ARM.com // Set the status to Squashing. 2797732SAli.Saidi@ARM.com _status = Squashing; 2807732SAli.Saidi@ARM.com 2817732SAli.Saidi@ARM.com numInst = 0; 2827732SAli.Saidi@ARM.com 2837732SAli.Saidi@ARM.com // Clear the skid buffer in case it has any data in it. 2847732SAli.Saidi@ARM.com while (!skidBuffer.empty()) 2857732SAli.Saidi@ARM.com { 2867732SAli.Saidi@ARM.com skidBuffer.pop(); 2877732SAli.Saidi@ARM.com } 2887732SAli.Saidi@ARM.com 2897732SAli.Saidi@ARM.com doSquash(); 2907732SAli.Saidi@ARM.com} 2917732SAli.Saidi@ARM.com 2927732SAli.Saidi@ARM.comtemplate<class Impl> 2937732SAli.Saidi@ARM.comvoid 2947732SAli.Saidi@ARM.comSimpleRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num) 2958204SAli.Saidi@ARM.com{ 2967732SAli.Saidi@ARM.com DPRINTF(Rename, "Rename: Removing a committed instruction from the " 2977732SAli.Saidi@ARM.com "history buffer, until sequence number %lli.\n", inst_seq_num); 2987732SAli.Saidi@ARM.com typename list<RenameHistory>::iterator hb_it = historyBuffer.end(); 2997732SAli.Saidi@ARM.com 3007732SAli.Saidi@ARM.com --hb_it; 3017732SAli.Saidi@ARM.com 3027732SAli.Saidi@ARM.com if (hb_it->instSeqNum > inst_seq_num) { 3037732SAli.Saidi@ARM.com DPRINTF(Rename, "Rename: Old sequence number encountered. Ensure " 3047732SAli.Saidi@ARM.com "that a syscall happened recently.\n"); 3057732SAli.Saidi@ARM.com return; 3067732SAli.Saidi@ARM.com } 3077732SAli.Saidi@ARM.com 3087732SAli.Saidi@ARM.com while ((*hb_it).instSeqNum != inst_seq_num) 3097732SAli.Saidi@ARM.com { 3107732SAli.Saidi@ARM.com // Make sure we haven't gone off the end of the list. 3117732SAli.Saidi@ARM.com assert(hb_it != historyBuffer.end()); 3127732SAli.Saidi@ARM.com 3137732SAli.Saidi@ARM.com // In theory instructions at the end of the history buffer 3147732SAli.Saidi@ARM.com // should be older than the instruction being removed, which 3157732SAli.Saidi@ARM.com // means they will have a lower sequence number. Also the 3167732SAli.Saidi@ARM.com // instruction being removed from the history really should 317 // be the last instruction in the list, as it is the instruction 318 // that was just committed that is being removed. 319 assert(hb_it->instSeqNum < inst_seq_num); 320 DPRINTF(Rename, "Rename: Freeing up older rename of reg %i, sequence" 321 " number %i.\n", 322 (*hb_it).prevPhysReg, (*hb_it).instSeqNum); 323 324 if (!(*hb_it).placeHolder) { 325 freeList->addReg((*hb_it).prevPhysReg); 326 ++renameCommittedMaps; 327 } 328 329 historyBuffer.erase(hb_it--); 330 } 331 332 // Finally free up the previous register of the finished instruction 333 // itself. 334 if (!(*hb_it).placeHolder) { 335 freeList->addReg(hb_it->prevPhysReg); 336 ++renameCommittedMaps; 337 } 338 339 historyBuffer.erase(hb_it); 340} 341 342template <class Impl> 343inline void 344SimpleRename<Impl>::renameSrcRegs(DynInstPtr &inst) 345{ 346 unsigned num_src_regs = inst->numSrcRegs(); 347 348 // Get the architectual register numbers from the source and 349 // destination operands, and redirect them to the right register. 350 // Will need to mark dependencies though. 351 for (int src_idx = 0; src_idx < num_src_regs; src_idx++) 352 { 353 RegIndex src_reg = inst->srcRegIdx(src_idx); 354 355 // Look up the source registers to get the phys. register they've 356 // been renamed to, and set the sources to those registers. 357 PhysRegIndex renamed_reg = renameMap->lookup(src_reg); 358 359 DPRINTF(Rename, "Rename: Looking up arch reg %i, got " 360 "physical reg %i.\n", (int)src_reg, (int)renamed_reg); 361 362 inst->renameSrcReg(src_idx, renamed_reg); 363 364 // Either incorporate it into the info passed back, 365 // or make another function call to see if that register is 366 // ready or not. 367 if (renameMap->isReady(renamed_reg)) { 368 DPRINTF(Rename, "Rename: Register is ready.\n"); 369 370 inst->markSrcRegReady(src_idx); 371 } 372 373 ++renameRenameLookups; 374 } 375} 376 377template <class Impl> 378inline void 379SimpleRename<Impl>::renameDestRegs(DynInstPtr &inst) 380{ 381 typename SimpleRenameMap::RenameInfo rename_result; 382 383 unsigned num_dest_regs = inst->numDestRegs(); 384 385 // If it's an instruction with no destination registers, then put 386 // a placeholder within the history buffer. It might be better 387 // to not put it in the history buffer at all (other than branches, 388 // which always need at least a place holder), and differentiate 389 // between instructions with and without destination registers 390 // when getting from commit the instructions that committed. 391 if (num_dest_regs == 0) { 392 RenameHistory hb_entry(inst->seqNum); 393 394 historyBuffer.push_front(hb_entry); 395 396 DPRINTF(Rename, "Rename: Adding placeholder instruction to " 397 "history buffer, sequence number %lli.\n", 398 inst->seqNum); 399 400 ++renameHBPlaceHolders; 401 } else { 402 403 // Rename the destination registers. 404 for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++) 405 { 406 RegIndex dest_reg = inst->destRegIdx(dest_idx); 407 408 // Get the physical register that the destination will be 409 // renamed to. 410 rename_result = renameMap->rename(dest_reg); 411 412 DPRINTF(Rename, "Rename: Renaming arch reg %i to physical " 413 "reg %i.\n", (int)dest_reg, 414 (int)rename_result.first); 415 416 // Record the rename information so that a history can be kept. 417 RenameHistory hb_entry(inst->seqNum, dest_reg, 418 rename_result.first, 419 rename_result.second); 420 421 historyBuffer.push_front(hb_entry); 422 423 DPRINTF(Rename, "Rename: Adding instruction to history buffer, " 424 "sequence number %lli.\n", 425 (*historyBuffer.begin()).instSeqNum); 426 427 // Tell the instruction to rename the appropriate destination 428 // register (dest_idx) to the new physical register 429 // (rename_result.first), and record the previous physical 430 // register that the same logical register was renamed to 431 // (rename_result.second). 432 inst->renameDestReg(dest_idx, 433 rename_result.first, 434 rename_result.second); 435 436 ++renameRenamedOperands; 437 } 438 } 439} 440 441template <class Impl> 442inline int 443SimpleRename<Impl>::calcFreeROBEntries() 444{ 445 return fromCommit->commitInfo.freeROBEntries - 446 renameWidth * iewToRenameDelay; 447} 448 449template <class Impl> 450inline int 451SimpleRename<Impl>::calcFreeIQEntries() 452{ 453 return fromIEW->iewInfo.freeIQEntries - renameWidth * iewToRenameDelay; 454} 455 456template<class Impl> 457void 458SimpleRename<Impl>::tick() 459{ 460 // Rename will need to try to rename as many instructions as it 461 // has bandwidth, unless it is blocked. 462 463 // Check if _status is BarrierStall. If so, then check if the number 464 // of free ROB entries is equal to the number of total ROB entries. 465 // Once equal then wake this stage up. Set status to unblocking maybe. 466 467 if (_status != Blocked && _status != Squashing) { 468 DPRINTF(Rename, "Rename: Status is not blocked, will attempt to " 469 "run stage.\n"); 470 // Make sure that the skid buffer has something in it if the 471 // status is unblocking. 472 assert(_status == Unblocking ? !skidBuffer.empty() : 1); 473 474 rename(); 475 476 // If the status was unblocking, then instructions from the skid 477 // buffer were used. Remove those instructions and handle 478 // the rest of unblocking. 479 if (_status == Unblocking) { 480 ++renameUnblockCycles; 481 482 if (fromDecode->size > 0) { 483 // Add the current inputs onto the skid buffer, so they can be 484 // reprocessed when this stage unblocks. 485 skidBuffer.push(*fromDecode); 486 } 487 488 unblock(); 489 } 490 } else if (_status == Blocked) { 491 ++renameBlockCycles; 492 493 // If stage is blocked and still receiving valid instructions, 494 // make sure to store them in the skid buffer. 495 if (fromDecode->size > 0) { 496 497 block(); 498 499 // Continue to tell previous stage to stall. 500 toDecode->renameInfo.stall = true; 501 } 502 503 if (!fromIEW->iewInfo.stall && 504 !fromCommit->commitInfo.stall && 505 calcFreeROBEntries() > 0 && 506 calcFreeIQEntries() > 0 && 507 renameMap->numFreeEntries() > 0) { 508 509 // Need to be sure to check all blocking conditions above. 510 // If they have cleared, then start unblocking. 511 DPRINTF(Rename, "Rename: Stall signals cleared, going to " 512 "unblock.\n"); 513 _status = Unblocking; 514 515 // Continue to tell previous stage to block until this stage 516 // is done unblocking. 517 toDecode->renameInfo.stall = true; 518 } else { 519 // Otherwise no conditions have changed. Tell previous 520 // stage to continue blocking. 521 toDecode->renameInfo.stall = true; 522 } 523 524 if (fromCommit->commitInfo.squash || 525 fromCommit->commitInfo.robSquashing) { 526 squash(); 527 return; 528 } 529 } else if (_status == Squashing) { 530 ++renameSquashCycles; 531 532 if (fromCommit->commitInfo.squash) { 533 squash(); 534 } else if (!fromCommit->commitInfo.squash && 535 !fromCommit->commitInfo.robSquashing) { 536 537 DPRINTF(Rename, "Rename: Done squashing, going to running.\n"); 538 _status = Running; 539 rename(); 540 } else { 541 doSquash(); 542 } 543 } 544 545 // Ugly code, revamp all of the tick() functions eventually. 546 if (fromCommit->commitInfo.doneSeqNum != 0 && _status != Squashing) { 547#if !FULL_SYSTEM 548 if (!fromCommit->commitInfo.squash) { 549 removeFromHistory(fromCommit->commitInfo.doneSeqNum); 550 } 551#else 552 removeFromHistory(fromCommit->commitInfo.doneSeqNum); 553#endif 554 } 555 556} 557 558template<class Impl> 559void 560SimpleRename<Impl>::rename() 561{ 562 // Check if any of the stages ahead of rename are telling rename 563 // to squash. The squash() function will also take care of fixing up 564 // the rename map and the free list. 565 if (fromCommit->commitInfo.squash || 566 fromCommit->commitInfo.robSquashing) { 567 DPRINTF(Rename, "Rename: Receiving signal from Commit to squash.\n"); 568 squash(); 569 return; 570 } 571 572 // Check if time buffer is telling this stage to stall. 573 if (fromIEW->iewInfo.stall || 574 fromCommit->commitInfo.stall) { 575 DPRINTF(Rename, "Rename: Receiving signal from IEW/Commit to " 576 "stall.\n"); 577 block(); 578 return; 579 } 580 581 // Check if the current status is squashing. If so, set its status 582 // to running and resume execution the next cycle. 583 if (_status == Squashing) { 584 DPRINTF(Rename, "Rename: Done squashing.\n"); 585 _status = Running; 586 return; 587 } 588 589 // Check the decode queue to see if instructions are available. 590 // If there are no available instructions to rename, then do nothing. 591 // Or, if the stage is currently unblocking, then go ahead and run it. 592 if (fromDecode->size == 0 && _status != Unblocking) { 593 DPRINTF(Rename, "Rename: Nothing to do, breaking out early.\n"); 594 // Should I change status to idle? 595 return; 596 } 597 598 //////////////////////////////////// 599 // Actual rename part. 600 //////////////////////////////////// 601 602 DynInstPtr inst; 603 604 // If we're unblocking, then we may be in the middle of an instruction 605 // group. Subtract off numInst to get the proper number of instructions 606 // left. 607 int insts_available = _status == Unblocking ? 608 skidBuffer.front().size - numInst : 609 fromDecode->size; 610 611 bool block_this_cycle = false; 612 613 // Will have to do a different calculation for the number of free 614 // entries. Number of free entries recorded on this cycle - 615 // renameWidth * renameToDecodeDelay 616 int free_rob_entries = calcFreeROBEntries(); 617 int free_iq_entries = calcFreeIQEntries(); 618 int min_iq_rob = min(free_rob_entries, free_iq_entries); 619 620 unsigned to_iew_index = 0; 621 622 // Check if there's any space left. 623 if (min_iq_rob <= 0) { 624 DPRINTF(Rename, "Rename: Blocking due to no free ROB or IQ " 625 "entries.\n" 626 "Rename: ROB has %d free entries.\n" 627 "Rename: IQ has %d free entries.\n", 628 free_rob_entries, 629 free_iq_entries); 630 block(); 631 // Tell previous stage to stall. 632 toDecode->renameInfo.stall = true; 633 634 if (free_rob_entries <= 0) { 635 ++renameROBFullEvents; 636 } else { 637 ++renameIQFullEvents; 638 } 639 640 return; 641 } else if (min_iq_rob < insts_available) { 642 DPRINTF(Rename, "Rename: Will have to block this cycle. Only " 643 "%i insts can be renamed due to IQ/ROB limits.\n", 644 min_iq_rob); 645 646 insts_available = min_iq_rob; 647 648 block_this_cycle = true; 649 650 if (free_rob_entries < free_iq_entries) { 651 ++renameROBFullEvents; 652 } else { 653 ++renameIQFullEvents; 654 } 655 } 656 657 while (insts_available > 0) { 658 DPRINTF(Rename, "Rename: Sending instructions to iew.\n"); 659 660 // Get the next instruction either from the skid buffer or the 661 // decode queue. 662 inst = _status == Unblocking ? skidBuffer.front().insts[numInst] : 663 fromDecode->insts[numInst]; 664 665 if (inst->isSquashed()) { 666 DPRINTF(Rename, "Rename: instruction %i with PC %#x is " 667 "squashed, skipping.\n", 668 inst->seqNum, inst->readPC()); 669 670 // Go to the next instruction. 671 ++numInst; 672 673 ++renameSquashedInsts; 674 675 // Decrement how many instructions are available. 676 --insts_available; 677 678 continue; 679 } 680 681 DPRINTF(Rename, "Rename: Processing instruction %i with PC %#x.\n", 682 inst->seqNum, inst->readPC()); 683 684 // If it's a trap instruction, then it needs to wait here within 685 // rename until the ROB is empty. Needs a way to detect that the 686 // ROB is empty. Maybe an event? 687 // Would be nice if it could be avoided putting this into a 688 // specific stage and instead just put it into the AlphaFullCPU. 689 // Might not really be feasible though... 690 // (EXCB, TRAPB) 691 if (inst->isSerializing()) { 692 panic("Rename: Serializing instruction encountered.\n"); 693 DPRINTF(Rename, "Rename: Serializing instruction " 694 "encountered.\n"); 695 696 // Change status over to BarrierStall so that other stages know 697 // what this is blocked on. 698 _status = BarrierStall; 699 700 block_this_cycle = true; 701 702 break; 703 } 704 705 // Check here to make sure there are enough destination registers 706 // to rename to. Otherwise block. 707 if (renameMap->numFreeEntries() < inst->numDestRegs()) 708 { 709 DPRINTF(Rename, "Rename: Blocking due to lack of free " 710 "physical registers to rename to.\n"); 711 // Need some sort of event based on a register being freed. 712 713 block_this_cycle = true; 714 715 ++renameFullRegistersEvents; 716 717 break; 718 } 719 720 renameSrcRegs(inst); 721 722 renameDestRegs(inst); 723 724 // Put instruction in rename queue. 725 toIEW->insts[to_iew_index] = inst; 726 ++(toIEW->size); 727 728 // Decrease the number of free ROB and IQ entries. 729 --free_rob_entries; 730 --free_iq_entries; 731 732 // Increment which instruction we're on. 733 ++to_iew_index; 734 ++numInst; 735 736 ++renameRenamedInsts; 737 738 // Decrement how many instructions are available. 739 --insts_available; 740 } 741 742 // Check if there's any instructions left that haven't yet been renamed. 743 // If so then block. 744 if (block_this_cycle) { 745 block(); 746 747 toDecode->renameInfo.stall = true; 748 } else { 749 // If we had a successful rename and didn't have to exit early, then 750 // reset numInst so it will refer to the correct instruction on next 751 // run. 752 numInst = 0; 753 } 754} 755