inst_queue_impl.hh revision 1684
1// Todo: 2// Current ordering allows for 0 cycle added-to-scheduled. Could maybe fake 3// it; either do in reverse order, or have added instructions put into a 4// different ready queue that, in scheduleRreadyInsts(), gets put onto the 5// normal ready queue. This would however give only a one cycle delay, 6// but probably is more flexible to actually add in a delay parameter than 7// just running it backwards. 8 9#include <vector> 10 11#include "sim/universe.hh" 12#include "cpu/beta_cpu/inst_queue.hh" 13 14// Either compile error or max int due to sign extension. 15// Blatant hack to avoid compile warnings. 16const InstSeqNum MaxInstSeqNum = 0 - 1; 17 18template <class Impl> 19InstructionQueue<Impl>::InstructionQueue(Params ¶ms) 20 : memDepUnit(params), 21 numEntries(params.numIQEntries), 22 intWidth(params.executeIntWidth), 23 floatWidth(params.executeFloatWidth), 24 branchWidth(params.executeBranchWidth), 25 memoryWidth(params.executeMemoryWidth), 26 totalWidth(params.issueWidth), 27 numPhysIntRegs(params.numPhysIntRegs), 28 numPhysFloatRegs(params.numPhysFloatRegs), 29 commitToIEWDelay(params.commitToIEWDelay) 30{ 31 // Initialize the number of free IQ entries. 32 freeEntries = numEntries; 33 34 // Set the number of physical registers as the number of int + float 35 numPhysRegs = numPhysIntRegs + numPhysFloatRegs; 36 37 DPRINTF(IQ, "IQ: There are %i physical registers.\n", numPhysRegs); 38 39 //Create an entry for each physical register within the 40 //dependency graph. 41 dependGraph = new DependencyEntry[numPhysRegs]; 42 43 // Resize the register scoreboard. 44 regScoreboard.resize(numPhysRegs); 45 46 // Initialize all the head pointers to point to NULL, and all the 47 // entries as unready. 48 // Note that in actuality, the registers corresponding to the logical 49 // registers start off as ready. However this doesn't matter for the 50 // IQ as the instruction should have been correctly told if those 51 // registers are ready in rename. Thus it can all be initialized as 52 // unready. 53 for (int i = 0; i < numPhysRegs; ++i) 54 { 55 dependGraph[i].next = NULL; 56 dependGraph[i].inst = NULL; 57 regScoreboard[i] = false; 58 } 59 60} 61 62template <class Impl> 63void 64InstructionQueue<Impl>::regStats() 65{ 66 iqInstsAdded 67 .name(name() + ".iqInstsAdded") 68 .desc("Number of instructions added to the IQ (excludes non-spec)") 69 .prereq(iqInstsAdded); 70 71 iqNonSpecInstsAdded 72 .name(name() + ".iqNonSpecInstsAdded") 73 .desc("Number of non-speculative instructions added to the IQ") 74 .prereq(iqNonSpecInstsAdded); 75 76// iqIntInstsAdded; 77 78 iqIntInstsIssued 79 .name(name() + ".iqIntInstsIssued") 80 .desc("Number of integer instructions issued") 81 .prereq(iqIntInstsIssued); 82 83// iqFloatInstsAdded; 84 85 iqFloatInstsIssued 86 .name(name() + ".iqFloatInstsIssued") 87 .desc("Number of float instructions issued") 88 .prereq(iqFloatInstsIssued); 89 90// iqBranchInstsAdded; 91 92 iqBranchInstsIssued 93 .name(name() + ".iqBranchInstsIssued") 94 .desc("Number of branch instructions issued") 95 .prereq(iqBranchInstsIssued); 96 97// iqMemInstsAdded; 98 99 iqMemInstsIssued 100 .name(name() + ".iqMemInstsIssued") 101 .desc("Number of memory instructions issued") 102 .prereq(iqMemInstsIssued); 103 104// iqMiscInstsAdded; 105 106 iqMiscInstsIssued 107 .name(name() + ".iqMiscInstsIssued") 108 .desc("Number of miscellaneous instructions issued") 109 .prereq(iqMiscInstsIssued); 110 111 iqSquashedInstsIssued 112 .name(name() + ".iqSquashedInstsIssued") 113 .desc("Number of squashed instructions issued") 114 .prereq(iqSquashedInstsIssued); 115 116 iqLoopSquashStalls 117 .name(name() + ".iqLoopSquashStalls") 118 .desc("Number of times issue loop had to restart due to squashed " 119 "inst; mainly for profiling") 120 .prereq(iqLoopSquashStalls); 121 122 iqSquashedInstsExamined 123 .name(name() + ".iqSquashedInstsExamined") 124 .desc("Number of squashed instructions iterated over during squash;" 125 " mainly for profiling") 126 .prereq(iqSquashedInstsExamined); 127 128 iqSquashedOperandsExamined 129 .name(name() + ".iqSquashedOperandsExamined") 130 .desc("Number of squashed operands that are examined and possibly " 131 "removed from graph") 132 .prereq(iqSquashedOperandsExamined); 133 134 iqSquashedNonSpecRemoved 135 .name(name() + ".iqSquashedNonSpecRemoved") 136 .desc("Number of squashed non-spec instructions that were removed") 137 .prereq(iqSquashedNonSpecRemoved); 138 139 // Tell mem dependence unit to reg stats as well. 140 memDepUnit.regStats(); 141} 142 143template <class Impl> 144void 145InstructionQueue<Impl>::setCPU(FullCPU *cpu_ptr) 146{ 147 cpu = cpu_ptr; 148 149 tail = cpu->instList.begin(); 150} 151 152template <class Impl> 153void 154InstructionQueue<Impl>::setIssueToExecuteQueue( 155 TimeBuffer<IssueStruct> *i2e_ptr) 156{ 157 DPRINTF(IQ, "IQ: Set the issue to execute queue.\n"); 158 issueToExecuteQueue = i2e_ptr; 159} 160 161template <class Impl> 162void 163InstructionQueue<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 164{ 165 DPRINTF(IQ, "IQ: Set the time buffer.\n"); 166 timeBuffer = tb_ptr; 167 168 fromCommit = timeBuffer->getWire(-commitToIEWDelay); 169} 170 171template <class Impl> 172unsigned 173InstructionQueue<Impl>::numFreeEntries() 174{ 175 return freeEntries; 176} 177 178// Might want to do something more complex if it knows how many instructions 179// will be issued this cycle. 180template <class Impl> 181bool 182InstructionQueue<Impl>::isFull() 183{ 184 if (freeEntries == 0) { 185 return(true); 186 } else { 187 return(false); 188 } 189} 190 191template <class Impl> 192void 193InstructionQueue<Impl>::insert(DynInstPtr &new_inst) 194{ 195 // Make sure the instruction is valid 196 assert(new_inst); 197 198 DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n", 199 new_inst->readPC()); 200 201 // Check if there are any free entries. Panic if there are none. 202 // Might want to have this return a fault in the future instead of 203 // panicing. 204 assert(freeEntries != 0); 205 206 // If the IQ currently has nothing in it, then there's a possibility 207 // that the tail iterator is invalid (might have been pointing at an 208 // instruction that was retired). Reset the tail iterator. 209 if (freeEntries == numEntries) { 210 tail = cpu->instList.begin(); 211 } 212 213 // Move the tail iterator. Instructions may not have been issued 214 // to the IQ, so we may have to increment the iterator more than once. 215 while ((*tail) != new_inst) { 216 tail++; 217 218 // Make sure the tail iterator points at something legal. 219 assert(tail != cpu->instList.end()); 220 } 221 222 223 // Decrease the number of free entries. 224 --freeEntries; 225 226 // Look through its source registers (physical regs), and mark any 227 // dependencies. 228 addToDependents(new_inst); 229 230 // Have this instruction set itself as the producer of its destination 231 // register(s). 232 createDependency(new_inst); 233 234 // If it's a memory instruction, add it to the memory dependency 235 // unit. 236 if (new_inst->isMemRef()) { 237 memDepUnit.insert(new_inst); 238 // Uh..forgot to look it up and put it on the proper dependency list 239 // if the instruction should not go yet. 240 } else { 241 // If the instruction is ready then add it to the ready list. 242 addIfReady(new_inst); 243 } 244 245 ++iqInstsAdded; 246 247 assert(freeEntries == (numEntries - countInsts())); 248} 249 250template <class Impl> 251void 252InstructionQueue<Impl>::insertNonSpec(DynInstPtr &inst) 253{ 254 nonSpecInsts[inst->seqNum] = inst; 255 256 // @todo: Clean up this code; can do it by setting inst as unable 257 // to issue, then calling normal insert on the inst. 258 259 // Make sure the instruction is valid 260 assert(inst); 261 262 DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n", 263 inst->readPC()); 264 265 // Check if there are any free entries. Panic if there are none. 266 // Might want to have this return a fault in the future instead of 267 // panicing. 268 assert(freeEntries != 0); 269 270 // If the IQ currently has nothing in it, then there's a possibility 271 // that the tail iterator is invalid (might have been pointing at an 272 // instruction that was retired). Reset the tail iterator. 273 if (freeEntries == numEntries) { 274 tail = cpu->instList.begin(); 275 } 276 277 // Move the tail iterator. Instructions may not have been issued 278 // to the IQ, so we may have to increment the iterator more than once. 279 while ((*tail) != inst) { 280 tail++; 281 282 // Make sure the tail iterator points at something legal. 283 assert(tail != cpu->instList.end()); 284 } 285 286 // Decrease the number of free entries. 287 --freeEntries; 288 289 // Have this instruction set itself as the producer of its destination 290 // register(s). 291 createDependency(inst); 292 293 // If it's a memory instruction, add it to the memory dependency 294 // unit. 295 if (inst->isMemRef()) { 296 memDepUnit.insertNonSpec(inst); 297 } 298 299 ++iqNonSpecInstsAdded; 300} 301 302// Slightly hack function to advance the tail iterator in the case that 303// the IEW stage issues an instruction that is not added to the IQ. This 304// is needed in case a long chain of such instructions occurs. 305// I don't think this is used anymore. 306template <class Impl> 307void 308InstructionQueue<Impl>::advanceTail(DynInstPtr &inst) 309{ 310 // Make sure the instruction is valid 311 assert(inst); 312 313 DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n", 314 inst->readPC()); 315 316 // Check if there are any free entries. Panic if there are none. 317 // Might want to have this return a fault in the future instead of 318 // panicing. 319 assert(freeEntries != 0); 320 321 // If the IQ currently has nothing in it, then there's a possibility 322 // that the tail iterator is invalid (might have been pointing at an 323 // instruction that was retired). Reset the tail iterator. 324 if (freeEntries == numEntries) { 325 tail = cpu->instList.begin(); 326 } 327 328 // Move the tail iterator. Instructions may not have been issued 329 // to the IQ, so we may have to increment the iterator more than once. 330 while ((*tail) != inst) { 331 tail++; 332 333 // Make sure the tail iterator points at something legal. 334 assert(tail != cpu->instList.end()); 335 } 336 337 assert(freeEntries <= numEntries); 338 339 // Have this instruction set itself as the producer of its destination 340 // register(s). 341 createDependency(inst); 342} 343 344// Need to make sure the number of float and integer instructions 345// issued does not exceed the total issue bandwidth. 346// @todo: Figure out a better way to remove the squashed items from the 347// lists. Checking the top item of each list to see if it's squashed 348// wastes time and forces jumps. 349template <class Impl> 350void 351InstructionQueue<Impl>::scheduleReadyInsts() 352{ 353 DPRINTF(IQ, "IQ: Attempting to schedule ready instructions from " 354 "the IQ.\n"); 355 356 int int_issued = 0; 357 int float_issued = 0; 358 int branch_issued = 0; 359 int memory_issued = 0; 360 int squashed_issued = 0; 361 int total_issued = 0; 362 363 IssueStruct *i2e_info = issueToExecuteQueue->access(0); 364 365 bool insts_available = !readyBranchInsts.empty() || 366 !readyIntInsts.empty() || 367 !readyFloatInsts.empty() || 368 !memDepUnit.empty() || 369 !readyMiscInsts.empty() || 370 !squashedInsts.empty(); 371 372 // Note: Requires a globally defined constant. 373 InstSeqNum oldest_inst = MaxInstSeqNum; 374 InstList list_with_oldest = None; 375 376 // Temporary values. 377 DynInstPtr int_head_inst; 378 DynInstPtr float_head_inst; 379 DynInstPtr branch_head_inst; 380 DynInstPtr mem_head_inst; 381 DynInstPtr misc_head_inst; 382 DynInstPtr squashed_head_inst; 383 384 // Somewhat nasty code to look at all of the lists where issuable 385 // instructions are located, and choose the oldest instruction among 386 // those lists. Consider a rewrite in the future. 387 while (insts_available && total_issued < totalWidth) 388 { 389 // Set this to false. Each if-block is required to set it to true 390 // if there were instructions available this check. This will cause 391 // this loop to run once more than necessary, but avoids extra calls. 392 insts_available = false; 393 394 oldest_inst = MaxInstSeqNum; 395 396 list_with_oldest = None; 397 398 if (!readyIntInsts.empty() && 399 int_issued < intWidth) { 400 401 insts_available = true; 402 403 int_head_inst = readyIntInsts.top(); 404 405 if (int_head_inst->isSquashed()) { 406 readyIntInsts.pop(); 407 408 ++iqLoopSquashStalls; 409 410 continue; 411 } 412 413 oldest_inst = int_head_inst->seqNum; 414 415 list_with_oldest = Int; 416 } 417 418 if (!readyFloatInsts.empty() && 419 float_issued < floatWidth) { 420 421 insts_available = true; 422 423 float_head_inst = readyFloatInsts.top(); 424 425 if (float_head_inst->isSquashed()) { 426 readyFloatInsts.pop(); 427 428 ++iqLoopSquashStalls; 429 430 continue; 431 } else if (float_head_inst->seqNum < oldest_inst) { 432 oldest_inst = float_head_inst->seqNum; 433 434 list_with_oldest = Float; 435 } 436 } 437 438 if (!readyBranchInsts.empty() && 439 branch_issued < branchWidth) { 440 441 insts_available = true; 442 443 branch_head_inst = readyBranchInsts.top(); 444 445 if (branch_head_inst->isSquashed()) { 446 readyBranchInsts.pop(); 447 448 ++iqLoopSquashStalls; 449 450 continue; 451 } else if (branch_head_inst->seqNum < oldest_inst) { 452 oldest_inst = branch_head_inst->seqNum; 453 454 list_with_oldest = Branch; 455 } 456 457 } 458 459 if (!memDepUnit.empty() && 460 memory_issued < memoryWidth) { 461 462 insts_available = true; 463 464 mem_head_inst = memDepUnit.top(); 465 466 if (mem_head_inst->isSquashed()) { 467 memDepUnit.pop(); 468 469 ++iqLoopSquashStalls; 470 471 continue; 472 } else if (mem_head_inst->seqNum < oldest_inst) { 473 oldest_inst = mem_head_inst->seqNum; 474 475 list_with_oldest = Memory; 476 } 477 } 478 479 if (!readyMiscInsts.empty()) { 480 481 insts_available = true; 482 483 misc_head_inst = readyMiscInsts.top(); 484 485 if (misc_head_inst->isSquashed()) { 486 readyMiscInsts.pop(); 487 488 ++iqLoopSquashStalls; 489 490 continue; 491 } else if (misc_head_inst->seqNum < oldest_inst) { 492 oldest_inst = misc_head_inst->seqNum; 493 494 list_with_oldest = Misc; 495 } 496 } 497 498 if (!squashedInsts.empty()) { 499 500 insts_available = true; 501 502 squashed_head_inst = squashedInsts.top(); 503 504 if (squashed_head_inst->seqNum < oldest_inst) { 505 list_with_oldest = Squashed; 506 } 507 508 } 509 510 DynInstPtr issuing_inst = NULL; 511 512 switch (list_with_oldest) { 513 case None: 514 DPRINTF(IQ, "IQ: Not able to schedule any instructions. Issuing " 515 "inst is %#x.\n", issuing_inst); 516 break; 517 518 case Int: 519 issuing_inst = int_head_inst; 520 readyIntInsts.pop(); 521 ++int_issued; 522 DPRINTF(IQ, "IQ: Issuing integer instruction PC %#x.\n", 523 issuing_inst->readPC()); 524 break; 525 526 case Float: 527 issuing_inst = float_head_inst; 528 readyFloatInsts.pop(); 529 ++float_issued; 530 DPRINTF(IQ, "IQ: Issuing float instruction PC %#x.\n", 531 issuing_inst->readPC()); 532 break; 533 534 case Branch: 535 issuing_inst = branch_head_inst; 536 readyBranchInsts.pop(); 537 ++branch_issued; 538 DPRINTF(IQ, "IQ: Issuing branch instruction PC %#x.\n", 539 issuing_inst->readPC()); 540 break; 541 542 case Memory: 543 issuing_inst = mem_head_inst; 544 545 memDepUnit.pop(); 546 ++memory_issued; 547 DPRINTF(IQ, "IQ: Issuing memory instruction PC %#x.\n", 548 issuing_inst->readPC()); 549 break; 550 551 case Misc: 552 issuing_inst = misc_head_inst; 553 readyMiscInsts.pop(); 554 555 ++iqMiscInstsIssued; 556 557 DPRINTF(IQ, "IQ: Issuing a miscellaneous instruction PC %#x.\n", 558 issuing_inst->readPC()); 559 break; 560 561 case Squashed: 562 assert(0 && "Squashed insts should not issue any more!"); 563 squashedInsts.pop(); 564 // Set the squashed instruction as able to commit so that commit 565 // can just drop it from the ROB. This is a bit faked. 566 ++squashed_issued; 567 ++freeEntries; 568 569 DPRINTF(IQ, "IQ: Issuing squashed instruction PC %#x.\n", 570 squashed_head_inst->readPC()); 571 break; 572 } 573 574 if (list_with_oldest != None && list_with_oldest != Squashed) { 575 i2e_info->insts[total_issued] = issuing_inst; 576 i2e_info->size++; 577 578 issuing_inst->setIssued(); 579 580 ++freeEntries; 581 ++total_issued; 582 } 583 584 assert(freeEntries == (numEntries - countInsts())); 585 } 586 587 iqIntInstsIssued += int_issued; 588 iqFloatInstsIssued += float_issued; 589 iqBranchInstsIssued += branch_issued; 590 iqMemInstsIssued += memory_issued; 591 iqSquashedInstsIssued += squashed_issued; 592} 593 594template <class Impl> 595void 596InstructionQueue<Impl>::scheduleNonSpec(const InstSeqNum &inst) 597{ 598 DPRINTF(IQ, "IQ: Marking nonspeculative instruction with sequence " 599 "number %i as ready to execute.\n", inst); 600 601 non_spec_it_t inst_it = nonSpecInsts.find(inst); 602 603 assert(inst_it != nonSpecInsts.end()); 604 605 // Mark this instruction as ready to issue. 606 (*inst_it).second->setCanIssue(); 607 608 // Now schedule the instruction. 609 if (!(*inst_it).second->isMemRef()) { 610 addIfReady((*inst_it).second); 611 } else { 612 memDepUnit.nonSpecInstReady((*inst_it).second); 613 } 614 615 nonSpecInsts.erase(inst_it); 616} 617 618template <class Impl> 619void 620InstructionQueue<Impl>::wakeDependents(DynInstPtr &completed_inst) 621{ 622 DPRINTF(IQ, "IQ: Waking dependents of completed instruction.\n"); 623 //Look at the physical destination register of the DynInst 624 //and look it up on the dependency graph. Then mark as ready 625 //any instructions within the instruction queue. 626 DependencyEntry *curr; 627 628 // Tell the memory dependence unit to wake any dependents on this 629 // instruction if it is a memory instruction. 630 631 if (completed_inst->isMemRef()) { 632 memDepUnit.wakeDependents(completed_inst); 633 } 634 635 for (int dest_reg_idx = 0; 636 dest_reg_idx < completed_inst->numDestRegs(); 637 dest_reg_idx++) 638 { 639 PhysRegIndex dest_reg = 640 completed_inst->renamedDestRegIdx(dest_reg_idx); 641 642 // Special case of uniq or control registers. They are not 643 // handled by the IQ and thus have no dependency graph entry. 644 // @todo Figure out a cleaner way to handle this. 645 if (dest_reg >= numPhysRegs) { 646 continue; 647 } 648 649 DPRINTF(IQ, "IQ: Waking any dependents on register %i.\n", 650 (int) dest_reg); 651 652 //Maybe abstract this part into a function. 653 //Go through the dependency chain, marking the registers as ready 654 //within the waiting instructions. 655 while (dependGraph[dest_reg].next) { 656 657 curr = dependGraph[dest_reg].next; 658 659 DPRINTF(IQ, "IQ: Waking up a dependent instruction, PC%#x.\n", 660 curr->inst->readPC()); 661 662 // Might want to give more information to the instruction 663 // so that it knows which of its source registers is ready. 664 // However that would mean that the dependency graph entries 665 // would need to hold the src_reg_idx. 666 curr->inst->markSrcRegReady(); 667 668 addIfReady(curr->inst); 669 670 dependGraph[dest_reg].next = curr->next; 671 672 DependencyEntry::mem_alloc_counter--; 673 674 curr->inst = NULL; 675 676 delete curr; 677 } 678 679 // Reset the head node now that all of its dependents have been woken 680 // up. 681 dependGraph[dest_reg].next = NULL; 682 dependGraph[dest_reg].inst = NULL; 683 684 // Mark the scoreboard as having that register ready. 685 regScoreboard[dest_reg] = true; 686 } 687} 688 689template <class Impl> 690void 691InstructionQueue<Impl>::violation(DynInstPtr &store, 692 DynInstPtr &faulting_load) 693{ 694 memDepUnit.violation(store, faulting_load); 695} 696 697template <class Impl> 698void 699InstructionQueue<Impl>::squash() 700{ 701 DPRINTF(IQ, "IQ: Starting to squash instructions in the IQ.\n"); 702 703 // Read instruction sequence number of last instruction out of the 704 // time buffer. 705 squashedSeqNum = fromCommit->commitInfo.doneSeqNum; 706 707 // Setup the squash iterator to point to the tail. 708 squashIt = tail; 709 710 // Call doSquash if there are insts in the IQ 711 if (freeEntries != numEntries) { 712 doSquash(); 713 } 714 715 // Also tell the memory dependence unit to squash. 716 memDepUnit.squash(squashedSeqNum); 717} 718 719template <class Impl> 720void 721InstructionQueue<Impl>::doSquash() 722{ 723 // Make sure the squash iterator isn't pointing to nothing. 724 assert(squashIt != cpu->instList.end()); 725 // Make sure the squashed sequence number is valid. 726 assert(squashedSeqNum != 0); 727 728 DPRINTF(IQ, "IQ: Squashing instructions in the IQ.\n"); 729 730 // Squash any instructions younger than the squashed sequence number 731 // given. 732 while ((*squashIt)->seqNum > squashedSeqNum) { 733 DynInstPtr squashed_inst = (*squashIt); 734 735 // Only handle the instruction if it actually is in the IQ and 736 // hasn't already been squashed in the IQ. 737 if (!squashed_inst->isIssued() && 738 !squashed_inst->isSquashedInIQ()) { 739 740 // Remove the instruction from the dependency list. 741 // Hack for now: These below don't add themselves to the 742 // dependency list, so don't try to remove them. 743 if (!squashed_inst->isNonSpeculative()/* && 744 !squashed_inst->isStore()*/ 745 ) { 746 747 for (int src_reg_idx = 0; 748 src_reg_idx < squashed_inst->numSrcRegs(); 749 src_reg_idx++) 750 { 751 PhysRegIndex src_reg = 752 squashed_inst->renamedSrcRegIdx(src_reg_idx); 753 754 // Only remove it from the dependency graph if it was 755 // placed there in the first place. 756 // HACK: This assumes that instructions woken up from the 757 // dependency chain aren't informed that a specific src 758 // register has become ready. This may not always be true 759 // in the future. 760 if (!squashed_inst->isReadySrcRegIdx(src_reg_idx) && 761 src_reg < numPhysRegs) { 762 dependGraph[src_reg].remove(squashed_inst); 763 } 764 765 ++iqSquashedOperandsExamined; 766 } 767 768 // Might want to remove producers as well. 769 } else { 770 nonSpecInsts[squashed_inst->seqNum] = NULL; 771 772 nonSpecInsts.erase(squashed_inst->seqNum); 773 774 ++iqSquashedNonSpecRemoved; 775 } 776 777 // Might want to also clear out the head of the dependency graph. 778 779 // Mark it as squashed within the IQ. 780 squashed_inst->setSquashedInIQ(); 781 782// squashedInsts.push(squashed_inst); 783 squashed_inst->setIssued(); 784 squashed_inst->setCanCommit(); 785 786 ++freeEntries; 787 788 DPRINTF(IQ, "IQ: Instruction PC %#x squashed.\n", 789 squashed_inst->readPC()); 790 } 791 792 --squashIt; 793 ++iqSquashedInstsExamined; 794 } 795 796 assert(freeEntries <= numEntries); 797 798 if (freeEntries == numEntries) { 799 tail = cpu->instList.end(); 800 } 801 802} 803 804template <class Impl> 805void 806InstructionQueue<Impl>::stopSquash() 807{ 808 // Clear up the squash variables to ensure that squashing doesn't 809 // get called improperly. 810 squashedSeqNum = 0; 811 812 squashIt = cpu->instList.end(); 813} 814 815template <class Impl> 816void 817InstructionQueue<Impl>::DependencyEntry::insert(DynInstPtr &new_inst) 818{ 819 //Add this new, dependent instruction at the head of the dependency 820 //chain. 821 822 // First create the entry that will be added to the head of the 823 // dependency chain. 824 DependencyEntry *new_entry = new DependencyEntry; 825 new_entry->next = this->next; 826 new_entry->inst = new_inst; 827 828 // Then actually add it to the chain. 829 this->next = new_entry; 830 831 ++mem_alloc_counter; 832} 833 834template <class Impl> 835void 836InstructionQueue<Impl>::DependencyEntry::remove(DynInstPtr &inst_to_remove) 837{ 838 DependencyEntry *prev = this; 839 DependencyEntry *curr = this->next; 840 841 // Make sure curr isn't NULL. Because this instruction is being 842 // removed from a dependency list, it must have been placed there at 843 // an earlier time. The dependency chain should not be empty, 844 // unless the instruction dependent upon it is already ready. 845 if (curr == NULL) { 846 return; 847 } 848 849 // Find the instruction to remove within the dependency linked list. 850 while(curr->inst != inst_to_remove) 851 { 852 prev = curr; 853 curr = curr->next; 854 855 assert(curr != NULL); 856 } 857 858 // Now remove this instruction from the list. 859 prev->next = curr->next; 860 861 --mem_alloc_counter; 862 863 // Could push this off to the destructor of DependencyEntry 864 curr->inst = NULL; 865 866 delete curr; 867} 868 869template <class Impl> 870bool 871InstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst) 872{ 873 // Loop through the instruction's source registers, adding 874 // them to the dependency list if they are not ready. 875 int8_t total_src_regs = new_inst->numSrcRegs(); 876 bool return_val = false; 877 878 for (int src_reg_idx = 0; 879 src_reg_idx < total_src_regs; 880 src_reg_idx++) 881 { 882 // Only add it to the dependency graph if it's not ready. 883 if (!new_inst->isReadySrcRegIdx(src_reg_idx)) { 884 PhysRegIndex src_reg = new_inst->renamedSrcRegIdx(src_reg_idx); 885 886 // Check the IQ's scoreboard to make sure the register 887 // hasn't become ready while the instruction was in flight 888 // between stages. Only if it really isn't ready should 889 // it be added to the dependency graph. 890 if (src_reg >= numPhysRegs) { 891 continue; 892 } else if (regScoreboard[src_reg] == false) { 893 DPRINTF(IQ, "IQ: Instruction PC %#x has src reg %i that " 894 "is being added to the dependency chain.\n", 895 new_inst->readPC(), src_reg); 896 897 dependGraph[src_reg].insert(new_inst); 898 899 // Change the return value to indicate that something 900 // was added to the dependency graph. 901 return_val = true; 902 } else { 903 DPRINTF(IQ, "IQ: Instruction PC %#x has src reg %i that " 904 "became ready before it reached the IQ.\n", 905 new_inst->readPC(), src_reg); 906 // Mark a register ready within the instruction. 907 new_inst->markSrcRegReady(); 908 } 909 } 910 } 911 912 return return_val; 913} 914 915template <class Impl> 916void 917InstructionQueue<Impl>::createDependency(DynInstPtr &new_inst) 918{ 919 //Actually nothing really needs to be marked when an 920 //instruction becomes the producer of a register's value, 921 //but for convenience a ptr to the producing instruction will 922 //be placed in the head node of the dependency links. 923 int8_t total_dest_regs = new_inst->numDestRegs(); 924 925 for (int dest_reg_idx = 0; 926 dest_reg_idx < total_dest_regs; 927 dest_reg_idx++) 928 { 929 PhysRegIndex dest_reg = new_inst->renamedDestRegIdx(dest_reg_idx); 930 931 // Instructions that use the misc regs will have a reg number 932 // higher than the normal physical registers. In this case these 933 // registers are not renamed, and there is no need to track 934 // dependencies as these instructions must be executed at commit. 935 if (dest_reg >= numPhysRegs) { 936 continue; 937 } 938 939 dependGraph[dest_reg].inst = new_inst; 940 941 if (dependGraph[dest_reg].next) { 942 dumpDependGraph(); 943 panic("IQ: Dependency graph not empty!"); 944 } 945 946 // Mark the scoreboard to say it's not yet ready. 947 regScoreboard[dest_reg] = false; 948 } 949} 950 951template <class Impl> 952void 953InstructionQueue<Impl>::addIfReady(DynInstPtr &inst) 954{ 955 //If the instruction now has all of its source registers 956 // available, then add it to the list of ready instructions. 957 if (inst->readyToIssue()) { 958 959 //Add the instruction to the proper ready list. 960 if (inst->isControl()) { 961 962 DPRINTF(IQ, "IQ: Branch instruction is ready to issue, " 963 "putting it onto the ready list, PC %#x.\n", 964 inst->readPC()); 965 readyBranchInsts.push(inst); 966 967 } else if (inst->isMemRef()) { 968 969 DPRINTF(IQ, "IQ: Checking if memory instruction can issue.\n"); 970 971 // Message to the mem dependence unit that this instruction has 972 // its registers ready. 973 974 memDepUnit.regsReady(inst); 975 976#if 0 977 if (memDepUnit.readyToIssue(inst)) { 978 DPRINTF(IQ, "IQ: Memory instruction is ready to issue, " 979 "putting it onto the ready list, PC %#x.\n", 980 inst->readPC()); 981 readyMemInsts.push(inst); 982 } else { 983 // Make dependent on the store. 984 // Will need some way to get the store instruction it should 985 // be dependent upon; then when the store issues it can 986 // put the instruction on the ready list. 987 // Yet another tree? 988 assert(0 && "Instruction has no way to actually issue"); 989 } 990#endif 991 992 } else if (inst->isInteger()) { 993 994 DPRINTF(IQ, "IQ: Integer instruction is ready to issue, " 995 "putting it onto the ready list, PC %#x.\n", 996 inst->readPC()); 997 readyIntInsts.push(inst); 998 999 } else if (inst->isFloating()) { 1000 1001 DPRINTF(IQ, "IQ: Floating instruction is ready to issue, " 1002 "putting it onto the ready list, PC %#x.\n", 1003 inst->readPC()); 1004 readyFloatInsts.push(inst); 1005 1006 } else { 1007 DPRINTF(IQ, "IQ: Miscellaneous instruction is ready to issue, " 1008 "putting it onto the ready list, PC %#x..\n", 1009 inst->readPC()); 1010 1011 readyMiscInsts.push(inst); 1012 } 1013 } 1014} 1015 1016/* 1017 * Caution, this function must not be called prior to tail being updated at 1018 * least once, otherwise it will fail the assertion. This is because 1019 * instList.begin() actually changes upon the insertion of an element into the 1020 * list when the list is empty. 1021 */ 1022template <class Impl> 1023int 1024InstructionQueue<Impl>::countInsts() 1025{ 1026 ListIt count_it = cpu->instList.begin(); 1027 int total_insts = 0; 1028 1029 if (tail == cpu->instList.end()) 1030 return 0; 1031 1032 while (count_it != tail) { 1033 if (!(*count_it)->isIssued()) { 1034 ++total_insts; 1035 } 1036 1037 ++count_it; 1038 1039 assert(count_it != cpu->instList.end()); 1040 } 1041 1042 // Need to count the tail iterator as well. 1043 if (count_it != cpu->instList.end() && 1044 (*count_it) && 1045 !(*count_it)->isIssued()) { 1046 ++total_insts; 1047 } 1048 1049 return total_insts; 1050} 1051 1052template <class Impl> 1053void 1054InstructionQueue<Impl>::dumpDependGraph() 1055{ 1056 DependencyEntry *curr; 1057 1058 for (int i = 0; i < numPhysRegs; ++i) 1059 { 1060 curr = &dependGraph[i]; 1061 1062 if (curr->inst) { 1063 cprintf("dependGraph[%i]: producer: %#x consumer: ", i, 1064 curr->inst->readPC()); 1065 } else { 1066 cprintf("dependGraph[%i]: No producer. consumer: ", i); 1067 } 1068 1069 while (curr->next != NULL) { 1070 curr = curr->next; 1071 1072 cprintf("%#x ", curr->inst->readPC()); 1073 } 1074 1075 cprintf("\n"); 1076 } 1077} 1078 1079template <class Impl> 1080void 1081InstructionQueue<Impl>::dumpLists() 1082{ 1083 cprintf("Ready integer list size: %i\n", readyIntInsts.size()); 1084 1085 cprintf("Ready float list size: %i\n", readyFloatInsts.size()); 1086 1087 cprintf("Ready branch list size: %i\n", readyBranchInsts.size()); 1088 1089 cprintf("Ready misc list size: %i\n", readyMiscInsts.size()); 1090 1091 cprintf("Squashed list size: %i\n", squashedInsts.size()); 1092 1093 cprintf("Non speculative list size: %i\n", nonSpecInsts.size()); 1094 1095 non_spec_it_t non_spec_it = nonSpecInsts.begin(); 1096 1097 cprintf("Non speculative list: "); 1098 1099 while (non_spec_it != nonSpecInsts.end()) { 1100 cprintf("%#x ", (*non_spec_it).second->readPC()); 1101 ++non_spec_it; 1102 } 1103 1104 cprintf("\n"); 1105 1106} 1107