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