rename_impl.hh revision 1061
1#include <list> 2 3#include "cpu/beta_cpu/rename.hh" 4 5template <class Impl> 6SimpleRename<Impl>::SimpleRename(Params ¶ms) 7 : iewToRenameDelay(params.iewToRenameDelay), 8 decodeToRenameDelay(params.decodeToRenameDelay), 9 commitToRenameDelay(params.commitToRenameDelay), 10 renameWidth(params.renameWidth), 11 commitWidth(params.commitWidth), 12 numInst(0) 13{ 14 _status = Idle; 15} 16 17template <class Impl> 18void 19SimpleRename<Impl>::setCPU(FullCPU *cpu_ptr) 20{ 21 DPRINTF(Rename, "Rename: Setting CPU pointer.\n"); 22 cpu = cpu_ptr; 23} 24 25template <class Impl> 26void 27SimpleRename<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 28{ 29 DPRINTF(Rename, "Rename: Setting time buffer pointer.\n"); 30 timeBuffer = tb_ptr; 31 32 // Setup wire to read information from time buffer, from IEW stage. 33 fromIEW = timeBuffer->getWire(-iewToRenameDelay); 34 35 // Setup wire to read infromation from time buffer, from commit stage. 36 fromCommit = timeBuffer->getWire(-commitToRenameDelay); 37 38 // Setup wire to write information to previous stages. 39 toDecode = timeBuffer->getWire(0); 40} 41 42template <class Impl> 43void 44SimpleRename<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr) 45{ 46 DPRINTF(Rename, "Rename: Setting rename queue pointer.\n"); 47 renameQueue = rq_ptr; 48 49 // Setup wire to write information to future stages. 50 toIEW = renameQueue->getWire(0); 51} 52 53template <class Impl> 54void 55SimpleRename<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr) 56{ 57 DPRINTF(Rename, "Rename: Setting decode queue pointer.\n"); 58 decodeQueue = dq_ptr; 59 60 // Setup wire to get information from decode. 61 fromDecode = decodeQueue->getWire(-decodeToRenameDelay); 62 63} 64 65template <class Impl> 66void 67SimpleRename<Impl>::setRenameMap(RenameMap *rm_ptr) 68{ 69 DPRINTF(Rename, "Rename: Setting rename map pointer.\n"); 70 renameMap = rm_ptr; 71} 72 73template <class Impl> 74void 75SimpleRename<Impl>::setFreeList(FreeList *fl_ptr) 76{ 77 DPRINTF(Rename, "Rename: Setting free list pointer.\n"); 78 freeList = fl_ptr; 79} 80 81template <class Impl> 82void 83SimpleRename<Impl>::dumpHistory() 84{ 85 typename list<RenameHistory>::iterator buf_it = historyBuffer.begin(); 86 87 while (buf_it != historyBuffer.end()) 88 { 89 cprintf("Seq num: %i\nArch reg: %i New phys reg: %i Old phys " 90 "reg: %i\n", (*buf_it).instSeqNum, (int)(*buf_it).archReg, 91 (int)(*buf_it).newPhysReg, (int)(*buf_it).prevPhysReg); 92 93 buf_it++; 94 } 95} 96 97template <class Impl> 98void 99SimpleRename<Impl>::block() 100{ 101 DPRINTF(Rename, "Rename: Blocking.\n"); 102 // Set status to Blocked. 103 _status = Blocked; 104 105 // Add the current inputs onto the skid buffer, so they can be 106 // reprocessed when this stage unblocks. 107 skidBuffer.push(*fromDecode); 108 109 // Note that this stage only signals previous stages to stall when 110 // it is the cause of the stall originates at this stage. Otherwise 111 // the previous stages are expected to check all possible stall signals. 112} 113 114template <class Impl> 115inline void 116SimpleRename<Impl>::unblock() 117{ 118 DPRINTF(Rename, "Rename: Read instructions out of skid buffer this " 119 "cycle.\n"); 120 // Remove the now processed instructions from the skid buffer. 121 skidBuffer.pop(); 122 123 // If there's still information in the skid buffer, then 124 // continue to tell previous stages to stall. They will be 125 // able to restart once the skid buffer is empty. 126 if (!skidBuffer.empty()) { 127 toDecode->renameInfo.stall = true; 128 } else { 129 DPRINTF(Rename, "Rename: Done unblocking.\n"); 130 _status = Running; 131 } 132} 133 134template <class Impl> 135void 136SimpleRename<Impl>::doSquash() 137{ 138 typename list<RenameHistory>::iterator hb_it = historyBuffer.begin(); 139// typename list<RenameHistory>::iterator delete_it; 140 141 InstSeqNum squashed_seq_num = fromCommit->commitInfo.doneSeqNum; 142 143#ifdef FULL_SYSTEM 144 assert(!historyBuffer.empty()); 145#else 146 // After a syscall squashes everything, the history buffer may be empty 147 // but the ROB may still be squashing instructions. 148 if (historyBuffer.empty()) { 149 return; 150 } 151#endif // FULL_SYSTEM 152 153 // Go through the most recent instructions, undoing the mappings 154 // they did and freeing up the registers. 155 while ((*hb_it).instSeqNum > squashed_seq_num) 156 { 157 DPRINTF(Rename, "Rename: Removing history entry with sequence " 158 "number %i.\n", (*hb_it).instSeqNum); 159 160 // If it's not simply a place holder, then add the registers. 161 if (!(*hb_it).placeHolder) { 162 // Tell the rename map to set the architected register to the 163 // previous physical register that it was renamed to. 164 renameMap->setEntry(hb_it->archReg, hb_it->prevPhysReg); 165 166 // Put the renamed physical register back on the free list. 167 freeList->addReg(hb_it->newPhysReg); 168 } 169 170// delete_it = hb_it; 171 172// hb_it++; 173 174 historyBuffer.erase(hb_it++); 175 176 assert(hb_it != historyBuffer.end()); 177 } 178} 179 180template <class Impl> 181void 182SimpleRename<Impl>::squash() 183{ 184 DPRINTF(Rename, "Rename: Squashing instructions.\n"); 185 // Set the status to Squashing. 186 _status = Squashing; 187 188 numInst = 0; 189 190 // Clear the skid buffer in case it has any data in it. 191 while (!skidBuffer.empty()) 192 { 193 skidBuffer.pop(); 194 } 195 196 doSquash(); 197} 198 199// In the future, when a SmartPtr is used for DynInst, then this function 200// itself can handle returning the instruction's physical registers to 201// the free list. 202template<class Impl> 203void 204SimpleRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num) 205{ 206 DPRINTF(Rename, "Rename: Removing a committed instruction from the " 207 "history buffer, until sequence number %lli.\n", inst_seq_num); 208 typename list<RenameHistory>::iterator hb_it = historyBuffer.end(); 209 210 --hb_it; 211 212 if (hb_it->instSeqNum > inst_seq_num) { 213 DPRINTF(Rename, "Rename: Old sequence number encountered. Ensure " 214 "that a syscall happened recently.\n"); 215 return; 216 } 217 218 while ((*hb_it).instSeqNum != inst_seq_num) 219 { 220 // Make sure we haven't gone off the end of the list. 221 assert(hb_it != historyBuffer.end()); 222 223 // In theory instructions at the end of the history buffer 224 // should be older than the instruction being removed, which 225 // means they will have a lower sequence number. Also the 226 // instruction being removed from the history really should 227 // be the last instruction in the list, as it is the instruction 228 // that was just committed that is being removed. 229 assert(hb_it->instSeqNum < inst_seq_num); 230 DPRINTF(Rename, "Rename: Freeing up older rename of reg %i, sequence" 231 " number %i.\n", 232 (*hb_it).prevPhysReg, (*hb_it).instSeqNum); 233 234 if (!(*hb_it).placeHolder) { 235 freeList->addReg((*hb_it).prevPhysReg); 236 } 237 238 historyBuffer.erase(hb_it--); 239 } 240 241 // Finally free up the previous register of the squashed instruction 242 // itself. 243 if (!(*hb_it).placeHolder) { 244 freeList->addReg(hb_it->prevPhysReg); 245 } 246 247 historyBuffer.erase(hb_it); 248 249} 250 251template <class Impl> 252inline void 253SimpleRename<Impl>::renameSrcRegs(DynInstPtr &inst) 254{ 255 unsigned num_src_regs = inst->numSrcRegs(); 256 257 // Get the architectual register numbers from the source and 258 // destination operands, and redirect them to the right register. 259 // Will need to mark dependencies though. 260 for (int src_idx = 0; src_idx < num_src_regs; src_idx++) 261 { 262 RegIndex src_reg = inst->srcRegIdx(src_idx); 263 264 // Look up the source registers to get the phys. register they've 265 // been renamed to, and set the sources to those registers. 266 RegIndex renamed_reg = renameMap->lookup(src_reg); 267 268 DPRINTF(Rename, "Rename: Looking up arch reg %i, got " 269 "physical reg %i.\n", (int)src_reg, (int)renamed_reg); 270 271 inst->renameSrcReg(src_idx, renamed_reg); 272 273 // Either incorporate it into the info passed back, 274 // or make another function call to see if that register is 275 // ready or not. 276 if (renameMap->isReady(renamed_reg)) { 277 DPRINTF(Rename, "Rename: Register is ready.\n"); 278 279 inst->markSrcRegReady(src_idx); 280 } 281 } 282} 283 284template <class Impl> 285inline void 286SimpleRename<Impl>::renameDestRegs(DynInstPtr &inst) 287{ 288 typename SimpleRenameMap::RenameInfo rename_result; 289 290 unsigned num_dest_regs = inst->numDestRegs(); 291 292 // Rename the destination registers. 293 for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++) 294 { 295 RegIndex dest_reg = inst->destRegIdx(dest_idx); 296 297 // Get the physical register that the destination will be 298 // renamed to. 299 rename_result = renameMap->rename(dest_reg); 300 301 DPRINTF(Rename, "Rename: Renaming arch reg %i to physical " 302 "reg %i.\n", (int)dest_reg, 303 (int)rename_result.first); 304 305 // Record the rename information so that a history can be kept. 306 RenameHistory hb_entry(inst->seqNum, dest_reg, 307 rename_result.first, 308 rename_result.second); 309 310 historyBuffer.push_front(hb_entry); 311 312 DPRINTF(Rename, "Rename: Adding instruction to history buffer, " 313 "sequence number %lli.\n", 314 (*historyBuffer.begin()).instSeqNum); 315 316 // Tell the instruction to rename the appropriate destination 317 // register (dest_idx) to the new physical register 318 // (rename_result.first), and record the previous physical 319 // register that the same logical register was renamed to 320 // (rename_result.second). 321 inst->renameDestReg(dest_idx, 322 rename_result.first, 323 rename_result.second); 324 } 325 326 // If it's an instruction with no destination registers, then put 327 // a placeholder within the history buffer. It might be better 328 // to not put it in the history buffer at all (other than branches, 329 // which always need at least a place holder), and differentiate 330 // between instructions with and without destination registers 331 // when getting from commit the instructions that committed. 332 if (num_dest_regs == 0) { 333 RenameHistory hb_entry(inst->seqNum); 334 335 historyBuffer.push_front(hb_entry); 336 337 DPRINTF(Rename, "Rename: Adding placeholder instruction to " 338 "history buffer, sequence number %lli.\n", 339 inst->seqNum); 340 } 341} 342 343template <class Impl> 344inline int 345SimpleRename<Impl>::calcFreeROBEntries() 346{ 347 return fromCommit->commitInfo.freeROBEntries - 348 renameWidth * iewToRenameDelay; 349} 350 351template <class Impl> 352inline int 353SimpleRename<Impl>::calcFreeIQEntries() 354{ 355 return fromIEW->iewInfo.freeIQEntries - renameWidth * iewToRenameDelay; 356} 357 358template<class Impl> 359void 360SimpleRename<Impl>::tick() 361{ 362 // Rename will need to try to rename as many instructions as it 363 // has bandwidth, unless it is blocked. 364 365 // Check if _status is BarrierStall. If so, then check if the number 366 // of free ROB entries is equal to the number of total ROB entries. 367 // Once equal then wake this stage up. Set status to unblocking maybe. 368 369 if (_status != Blocked && _status != Squashing) { 370 DPRINTF(Rename, "Rename: Status is not blocked, will attempt to " 371 "run stage.\n"); 372 // Make sure that the skid buffer has something in it if the 373 // status is unblocking. 374 assert(_status == Unblocking ? !skidBuffer.empty() : 1); 375 376 rename(); 377 378 // If the status was unblocking, then instructions from the skid 379 // buffer were used. Remove those instructions and handle 380 // the rest of unblocking. 381 if (_status == Unblocking) { 382 if (fromDecode->size > 0) { 383 // Add the current inputs onto the skid buffer, so they can be 384 // reprocessed when this stage unblocks. 385 skidBuffer.push(*fromDecode); 386 } 387 388 unblock(); 389 } 390 } else if (_status == Blocked) { 391 // If stage is blocked and still receiving valid instructions, 392 // make sure to store them in the skid buffer. 393 if (fromDecode->size > 0) { 394 395 block(); 396 397 // Continue to tell previous stage to stall. 398 toDecode->renameInfo.stall = true; 399 } 400 401 if (!fromIEW->iewInfo.stall && 402 !fromCommit->commitInfo.stall && 403 calcFreeROBEntries() > 0 && 404 calcFreeIQEntries() > 0 && 405 renameMap->numFreeEntries() > 0) { 406 407 // Need to be sure to check all blocking conditions above. 408 // If they have cleared, then start unblocking. 409 DPRINTF(Rename, "Rename: Stall signals cleared, going to " 410 "unblock.\n"); 411 _status = Unblocking; 412 413 // Continue to tell previous stage to block until this stage 414 // is done unblocking. 415 toDecode->renameInfo.stall = true; 416 } else { 417 // Otherwise no conditions have changed. Tell previous 418 // stage to continue blocking. 419 toDecode->renameInfo.stall = true; 420 } 421 422 if (fromCommit->commitInfo.squash || 423 fromCommit->commitInfo.robSquashing) { 424 squash(); 425 return; 426 } 427 } else if (_status == Squashing) { 428 if (fromCommit->commitInfo.squash) { 429 squash(); 430 } else if (!fromCommit->commitInfo.squash && 431 !fromCommit->commitInfo.robSquashing) { 432 433 DPRINTF(Rename, "Rename: Done squashing, going to running.\n"); 434 _status = Running; 435 } else { 436 doSquash(); 437 } 438 } 439 440 // Ugly code, revamp all of the tick() functions eventually. 441 if (fromCommit->commitInfo.doneSeqNum != 0 && _status != Squashing) { 442 removeFromHistory(fromCommit->commitInfo.doneSeqNum); 443 } 444 445 // Perhaps put this outside of this function, since this will 446 // happen regardless of whether or not the stage is blocked or 447 // squashing. 448 // Read from the time buffer any necessary data. 449 // Read registers that are freed, and add them to the freelist. 450 // This is unnecessary due to the history buffer (assuming the history 451 // buffer works properly). 452/* 453 while(!fromCommit->commitInfo.freeRegs.empty()) 454 { 455 PhysRegIndex freed_reg = fromCommit->commitInfo.freeRegs.back(); 456 DPRINTF(Rename, "Rename: Adding freed register %i to freelist.\n", 457 (int)freed_reg); 458 freeList->addReg(freed_reg); 459 460 fromCommit->commitInfo.freeRegs.pop_back(); 461 } 462*/ 463 464} 465 466template<class Impl> 467void 468SimpleRename<Impl>::rename() 469{ 470 // Check if any of the stages ahead of rename are telling rename 471 // to squash. The squash() function will also take care of fixing up 472 // the rename map and the free list. 473 if (fromCommit->commitInfo.squash || 474 fromCommit->commitInfo.robSquashing) { 475 DPRINTF(Rename, "Rename: Receiving signal from Commit to squash.\n"); 476 squash(); 477 return; 478 } 479 480 // Check if time buffer is telling this stage to stall. 481 if (fromIEW->iewInfo.stall || 482 fromCommit->commitInfo.stall) { 483 DPRINTF(Rename, "Rename: Receiving signal from IEW/Commit to " 484 "stall.\n"); 485 block(); 486 return; 487 } 488 489 // Check if the current status is squashing. If so, set its status 490 // to running and resume execution the next cycle. 491 if (_status == Squashing) { 492 DPRINTF(Rename, "Rename: Done squashing.\n"); 493 _status = Running; 494 return; 495 } 496 497 // Check the decode queue to see if instructions are available. 498 // If there are no available instructions to rename, then do nothing. 499 // Or, if the stage is currently unblocking, then go ahead and run it. 500 if (fromDecode->size == 0 && _status != Unblocking) { 501 DPRINTF(Rename, "Rename: Nothing to do, breaking out early.\n"); 502 // Should I change status to idle? 503 return; 504 } 505 506 //////////////////////////////////// 507 // Actual rename part. 508 //////////////////////////////////// 509 510 DynInstPtr inst; 511 512 // If we're unblocking, then we may be in the middle of an instruction 513 // group. Subtract off numInst to get the proper number of instructions 514 // left. 515 int insts_available = _status == Unblocking ? 516 skidBuffer.front().size - numInst : 517 fromDecode->size; 518 519 bool block_this_cycle = false; 520 521 // Will have to do a different calculation for the number of free 522 // entries. Number of free entries recorded on this cycle - 523 // renameWidth * renameToDecodeDelay 524 int free_rob_entries = calcFreeROBEntries(); 525 int free_iq_entries = calcFreeIQEntries(); 526 int min_iq_rob = min(free_rob_entries, free_iq_entries); 527 528 unsigned to_iew_index = 0; 529 530 // Check if there's any space left. 531 if (min_iq_rob <= 0) { 532 DPRINTF(Rename, "Rename: Blocking due to no free ROB or IQ " 533 "entries.\n" 534 "Rename: ROB has %d free entries.\n" 535 "Rename: IQ has %d free entries.\n", 536 free_rob_entries, 537 free_iq_entries); 538 block(); 539 // Tell previous stage to stall. 540 toDecode->renameInfo.stall = true; 541 542 return; 543 } else if (min_iq_rob < insts_available) { 544 DPRINTF(Rename, "Rename: Will have to block this cycle. Only " 545 "%i insts can be renamed due to IQ/ROB limits.\n", 546 min_iq_rob); 547 548 insts_available = min_iq_rob; 549 550 block_this_cycle = true; 551 } 552 553 while (insts_available > 0) { 554 DPRINTF(Rename, "Rename: Sending instructions to iew.\n"); 555 556 // Get the next instruction either from the skid buffer or the 557 // decode queue. 558 inst = _status == Unblocking ? skidBuffer.front().insts[numInst] : 559 fromDecode->insts[numInst]; 560 561 if (inst->isSquashed()) { 562 DPRINTF(Rename, "Rename: instruction %i with PC %#x is " 563 "squashed, skipping.\n", 564 inst->seqNum, inst->readPC()); 565 566 // Go to the next instruction. 567 ++numInst; 568 569 // Decrement how many instructions are available. 570 --insts_available; 571 572 continue; 573 } 574 575 DPRINTF(Rename, "Rename: Processing instruction %i with PC %#x.\n", 576 inst->seqNum, inst->readPC()); 577 578 // If it's a trap instruction, then it needs to wait here within 579 // rename until the ROB is empty. Needs a way to detect that the 580 // ROB is empty. Maybe an event? 581 // Would be nice if it could be avoided putting this into a 582 // specific stage and instead just put it into the AlphaFullCPU. 583 // Might not really be feasible though... 584 // (EXCB, TRAPB) 585 if (inst->isSerializing()) { 586 panic("Rename: Serializing instruction encountered.\n"); 587 DPRINTF(Rename, "Rename: Serializing instruction " 588 "encountered.\n"); 589 590 // Change status over to BarrierStall so that other stages know 591 // what this is blocked on. 592 _status = BarrierStall; 593 594 block_this_cycle = true; 595 596 break; 597 } 598 599 // Check here to make sure there are enough destination registers 600 // to rename to. Otherwise block. 601 if (renameMap->numFreeEntries() < inst->numDestRegs()) 602 { 603 DPRINTF(Rename, "Rename: Blocking due to lack of free " 604 "physical registers to rename to.\n"); 605 // Need some sort of event based on a register being freed. 606 607 block_this_cycle = true; 608 609 break; 610 } 611 612 renameSrcRegs(inst); 613 614 renameDestRegs(inst); 615 616 // Put instruction in rename queue. 617 toIEW->insts[to_iew_index] = inst; 618 ++(toIEW->size); 619 620 // Decrease the number of free ROB and IQ entries. 621 --free_rob_entries; 622 --free_iq_entries; 623 624 // Increment which instruction we're on. 625 ++to_iew_index; 626 ++numInst; 627 628 // Decrement how many instructions are available. 629 --insts_available; 630 } 631 632 // Check if there's any instructions left that haven't yet been renamed. 633 // If so then block. 634 if (block_this_cycle) { 635 block(); 636 637 toDecode->renameInfo.stall = true; 638 } else { 639 // If we had a successful rename and didn't have to exit early, then 640 // reset numInst so it will refer to the correct instruction on next 641 // run. 642 numInst = 0; 643 } 644} 645