lsq_unit_impl.hh revision 2361
1/* 2 * Copyright (c) 2004-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include "cpu/checker/cpu.hh" 30#include "cpu/o3/lsq_unit.hh" 31#include "base/str.hh" 32 33template <class Impl> 34LSQUnit<Impl>::StoreCompletionEvent::StoreCompletionEvent(int store_idx, 35 Event *wb_event, 36 LSQUnit<Impl> *lsq_ptr) 37 : Event(&mainEventQueue), 38 wbEvent(wb_event), 39 storeIdx(store_idx), 40 lsqPtr(lsq_ptr) 41{ 42 this->setFlags(Event::AutoDelete); 43} 44 45template <class Impl> 46void 47LSQUnit<Impl>::StoreCompletionEvent::process() 48{ 49 DPRINTF(LSQ, "Cache miss complete for store idx:%i\n", storeIdx); 50 DPRINTF(Activity, "Activity: st writeback event idx:%i\n", storeIdx); 51 52 //lsqPtr->removeMSHR(lsqPtr->storeQueue[storeIdx].inst->seqNum); 53 54 if (lsqPtr->isSwitchedOut()) { 55 if (wbEvent) 56 delete wbEvent; 57 58 return; 59 } 60 61 lsqPtr->cpu->wakeCPU(); 62 if (wbEvent) { 63 wbEvent->process(); 64 delete wbEvent; 65 } 66 lsqPtr->completeStore(storeIdx); 67} 68 69template <class Impl> 70const char * 71LSQUnit<Impl>::StoreCompletionEvent::description() 72{ 73 return "LSQ store completion event"; 74} 75 76template <class Impl> 77LSQUnit<Impl>::LSQUnit() 78 : loads(0), stores(0), storesToWB(0), stalled(false), isLoadBlocked(false), 79 loadBlockedHandled(false) 80{ 81} 82 83template<class Impl> 84void 85LSQUnit<Impl>::init(Params *params, unsigned maxLQEntries, 86 unsigned maxSQEntries, unsigned id) 87 88{ 89 DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id); 90 91 switchedOut = false; 92 93 lsqID = id; 94 95 // Add 1 for the sentinel entry (they are circular queues). 96 LQEntries = maxLQEntries + 1; 97 SQEntries = maxSQEntries + 1; 98 99 loadQueue.resize(LQEntries); 100 storeQueue.resize(SQEntries); 101 102 loadHead = loadTail = 0; 103 104 storeHead = storeWBIdx = storeTail = 0; 105 106 usedPorts = 0; 107 cachePorts = params->cachePorts; 108 109 dcacheInterface = params->dcacheInterface; 110 111 memDepViolator = NULL; 112 113 blockedLoadSeqNum = 0; 114} 115 116template<class Impl> 117std::string 118LSQUnit<Impl>::name() const 119{ 120 if (Impl::MaxThreads == 1) { 121 return iewStage->name() + ".lsq"; 122 } else { 123 return iewStage->name() + ".lsq.thread." + to_string(lsqID); 124 } 125} 126 127template<class Impl> 128void 129LSQUnit<Impl>::regStats() 130{ 131 lsqForwLoads 132 .name(name() + ".forwLoads") 133 .desc("Number of loads that had data forwarded from stores"); 134 135 invAddrLoads 136 .name(name() + ".invAddrLoads") 137 .desc("Number of loads ignored due to an invalid address"); 138 139 lsqSquashedLoads 140 .name(name() + ".squashedLoads") 141 .desc("Number of loads squashed"); 142 143 lsqIgnoredResponses 144 .name(name() + ".ignoredResponses") 145 .desc("Number of memory responses ignored because the instruction is squashed"); 146 147 lsqMemOrderViolation 148 .name(name() + ".memOrderViolation") 149 .desc("Number of memory ordering violations"); 150 151 lsqSquashedStores 152 .name(name() + ".squashedStores") 153 .desc("Number of stores squashed"); 154 155 invAddrSwpfs 156 .name(name() + ".invAddrSwpfs") 157 .desc("Number of software prefetches ignored due to an invalid address"); 158 159 lsqBlockedLoads 160 .name(name() + ".blockedLoads") 161 .desc("Number of blocked loads due to partial load-store forwarding"); 162 163 lsqRescheduledLoads 164 .name(name() + ".rescheduledLoads") 165 .desc("Number of loads that were rescheduled"); 166 167 lsqCacheBlocked 168 .name(name() + ".cacheBlocked") 169 .desc("Number of times an access to memory failed due to the cache being blocked"); 170} 171 172template<class Impl> 173void 174LSQUnit<Impl>::clearLQ() 175{ 176 loadQueue.clear(); 177} 178 179template<class Impl> 180void 181LSQUnit<Impl>::clearSQ() 182{ 183 storeQueue.clear(); 184} 185 186#if 0 187template<class Impl> 188void 189LSQUnit<Impl>::setPageTable(PageTable *pt_ptr) 190{ 191 DPRINTF(LSQUnit, "Setting the page table pointer.\n"); 192 pTable = pt_ptr; 193} 194#endif 195 196template<class Impl> 197void 198LSQUnit<Impl>::switchOut() 199{ 200 switchedOut = true; 201 for (int i = 0; i < loadQueue.size(); ++i) 202 loadQueue[i] = NULL; 203 204 assert(storesToWB == 0); 205 206 while (storesToWB > 0 && 207 storeWBIdx != storeTail && 208 storeQueue[storeWBIdx].inst && 209 storeQueue[storeWBIdx].canWB) { 210 211 if (storeQueue[storeWBIdx].size == 0 || 212 storeQueue[storeWBIdx].inst->isDataPrefetch() || 213 storeQueue[storeWBIdx].committed || 214 storeQueue[storeWBIdx].req->flags & LOCKED) { 215 incrStIdx(storeWBIdx); 216 217 continue; 218 } 219 220 assert(storeQueue[storeWBIdx].req); 221 assert(!storeQueue[storeWBIdx].committed); 222 223 MemReqPtr req = storeQueue[storeWBIdx].req; 224 storeQueue[storeWBIdx].committed = true; 225 226 req->cmd = Write; 227 req->completionEvent = NULL; 228 req->time = curTick; 229 assert(!req->data); 230 req->data = new uint8_t[64]; 231 memcpy(req->data, (uint8_t *)&storeQueue[storeWBIdx].data, req->size); 232 233 DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x " 234 "to Addr:%#x, data:%#x [sn:%lli]\n", 235 storeWBIdx,storeQueue[storeWBIdx].inst->readPC(), 236 req->paddr, *(req->data), 237 storeQueue[storeWBIdx].inst->seqNum); 238 239 switch(storeQueue[storeWBIdx].size) { 240 case 1: 241 cpu->write(req, (uint8_t &)storeQueue[storeWBIdx].data); 242 break; 243 case 2: 244 cpu->write(req, (uint16_t &)storeQueue[storeWBIdx].data); 245 break; 246 case 4: 247 cpu->write(req, (uint32_t &)storeQueue[storeWBIdx].data); 248 break; 249 case 8: 250 cpu->write(req, (uint64_t &)storeQueue[storeWBIdx].data); 251 break; 252 default: 253 panic("Unexpected store size!\n"); 254 } 255 incrStIdx(storeWBIdx); 256 } 257} 258 259template<class Impl> 260void 261LSQUnit<Impl>::takeOverFrom() 262{ 263 switchedOut = false; 264 loads = stores = storesToWB = 0; 265 266 loadHead = loadTail = 0; 267 268 storeHead = storeWBIdx = storeTail = 0; 269 270 usedPorts = 0; 271 272 memDepViolator = NULL; 273 274 blockedLoadSeqNum = 0; 275 276 stalled = false; 277 isLoadBlocked = false; 278 loadBlockedHandled = false; 279} 280 281template<class Impl> 282void 283LSQUnit<Impl>::resizeLQ(unsigned size) 284{ 285 unsigned size_plus_sentinel = size + 1; 286 assert(size_plus_sentinel >= LQEntries); 287 288 if (size_plus_sentinel > LQEntries) { 289 while (size_plus_sentinel > loadQueue.size()) { 290 DynInstPtr dummy; 291 loadQueue.push_back(dummy); 292 LQEntries++; 293 } 294 } else { 295 LQEntries = size_plus_sentinel; 296 } 297 298} 299 300template<class Impl> 301void 302LSQUnit<Impl>::resizeSQ(unsigned size) 303{ 304 unsigned size_plus_sentinel = size + 1; 305 if (size_plus_sentinel > SQEntries) { 306 while (size_plus_sentinel > storeQueue.size()) { 307 SQEntry dummy; 308 storeQueue.push_back(dummy); 309 SQEntries++; 310 } 311 } else { 312 SQEntries = size_plus_sentinel; 313 } 314} 315 316template <class Impl> 317void 318LSQUnit<Impl>::insert(DynInstPtr &inst) 319{ 320 assert(inst->isMemRef()); 321 322 assert(inst->isLoad() || inst->isStore()); 323 324 if (inst->isLoad()) { 325 insertLoad(inst); 326 } else { 327 insertStore(inst); 328 } 329 330 inst->setInLSQ(); 331} 332 333template <class Impl> 334void 335LSQUnit<Impl>::insertLoad(DynInstPtr &load_inst) 336{ 337 assert((loadTail + 1) % LQEntries != loadHead); 338 assert(loads < LQEntries); 339 340 DPRINTF(LSQUnit, "Inserting load PC %#x, idx:%i [sn:%lli]\n", 341 load_inst->readPC(), loadTail, load_inst->seqNum); 342 343 load_inst->lqIdx = loadTail; 344 345 if (stores == 0) { 346 load_inst->sqIdx = -1; 347 } else { 348 load_inst->sqIdx = storeTail; 349 } 350 351 loadQueue[loadTail] = load_inst; 352 353 incrLdIdx(loadTail); 354 355 ++loads; 356} 357 358template <class Impl> 359void 360LSQUnit<Impl>::insertStore(DynInstPtr &store_inst) 361{ 362 // Make sure it is not full before inserting an instruction. 363 assert((storeTail + 1) % SQEntries != storeHead); 364 assert(stores < SQEntries); 365 366 DPRINTF(LSQUnit, "Inserting store PC %#x, idx:%i [sn:%lli]\n", 367 store_inst->readPC(), storeTail, store_inst->seqNum); 368 369 store_inst->sqIdx = storeTail; 370 store_inst->lqIdx = loadTail; 371 372 storeQueue[storeTail] = SQEntry(store_inst); 373 374 incrStIdx(storeTail); 375 376 ++stores; 377} 378 379template <class Impl> 380typename Impl::DynInstPtr 381LSQUnit<Impl>::getMemDepViolator() 382{ 383 DynInstPtr temp = memDepViolator; 384 385 memDepViolator = NULL; 386 387 return temp; 388} 389 390template <class Impl> 391unsigned 392LSQUnit<Impl>::numFreeEntries() 393{ 394 unsigned free_lq_entries = LQEntries - loads; 395 unsigned free_sq_entries = SQEntries - stores; 396 397 // Both the LQ and SQ entries have an extra dummy entry to differentiate 398 // empty/full conditions. Subtract 1 from the free entries. 399 if (free_lq_entries < free_sq_entries) { 400 return free_lq_entries - 1; 401 } else { 402 return free_sq_entries - 1; 403 } 404} 405 406template <class Impl> 407int 408LSQUnit<Impl>::numLoadsReady() 409{ 410 int load_idx = loadHead; 411 int retval = 0; 412 413 while (load_idx != loadTail) { 414 assert(loadQueue[load_idx]); 415 416 if (loadQueue[load_idx]->readyToIssue()) { 417 ++retval; 418 } 419 } 420 421 return retval; 422} 423 424template <class Impl> 425Fault 426LSQUnit<Impl>::executeLoad(DynInstPtr &inst) 427{ 428 // Execute a specific load. 429 Fault load_fault = NoFault; 430 431 DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n", 432 inst->readPC(),inst->seqNum); 433 434// load_fault = inst->initiateAcc(); 435 load_fault = inst->execute(); 436 437 // If the instruction faulted, then we need to send it along to commit 438 // without the instruction completing. 439 if (load_fault != NoFault) { 440 // Send this instruction to commit, also make sure iew stage 441 // realizes there is activity. 442 iewStage->instToCommit(inst); 443 iewStage->activityThisCycle(); 444 } 445 446 return load_fault; 447} 448 449template <class Impl> 450Fault 451LSQUnit<Impl>::executeStore(DynInstPtr &store_inst) 452{ 453 using namespace TheISA; 454 // Make sure that a store exists. 455 assert(stores != 0); 456 457 int store_idx = store_inst->sqIdx; 458 459 DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n", 460 store_inst->readPC(), store_inst->seqNum); 461 462 // Check the recently completed loads to see if any match this store's 463 // address. If so, then we have a memory ordering violation. 464 int load_idx = store_inst->lqIdx; 465 466 Fault store_fault = store_inst->initiateAcc(); 467// Fault store_fault = store_inst->execute(); 468 469 if (storeQueue[store_idx].size == 0) { 470 DPRINTF(LSQUnit,"Fault on Store PC %#x, [sn:%lli],Size = 0\n", 471 store_inst->readPC(),store_inst->seqNum); 472 473 return store_fault; 474 } 475 476 assert(store_fault == NoFault); 477 478 if (store_inst->isStoreConditional()) { 479 // Store conditionals need to set themselves as able to 480 // writeback if we haven't had a fault by here. 481 storeQueue[store_idx].canWB = true; 482 483 ++storesToWB; 484 } 485 486 if (!memDepViolator) { 487 while (load_idx != loadTail) { 488 // Really only need to check loads that have actually executed 489 // It's safe to check all loads because effAddr is set to 490 // InvalAddr when the dyn inst is created. 491 492 // @todo: For now this is extra conservative, detecting a 493 // violation if the addresses match assuming all accesses 494 // are quad word accesses. 495 496 // @todo: Fix this, magic number being used here 497 if ((loadQueue[load_idx]->effAddr >> 8) == 498 (store_inst->effAddr >> 8)) { 499 // A load incorrectly passed this store. Squash and refetch. 500 // For now return a fault to show that it was unsuccessful. 501 memDepViolator = loadQueue[load_idx]; 502 ++lsqMemOrderViolation; 503 504 return genMachineCheckFault(); 505 } 506 507 incrLdIdx(load_idx); 508 } 509 510 // If we've reached this point, there was no violation. 511 memDepViolator = NULL; 512 } 513 514 return store_fault; 515} 516 517template <class Impl> 518void 519LSQUnit<Impl>::commitLoad() 520{ 521 assert(loadQueue[loadHead]); 522 523 DPRINTF(LSQUnit, "Committing head load instruction, PC %#x\n", 524 loadQueue[loadHead]->readPC()); 525 526 loadQueue[loadHead] = NULL; 527 528 incrLdIdx(loadHead); 529 530 --loads; 531} 532 533template <class Impl> 534void 535LSQUnit<Impl>::commitLoads(InstSeqNum &youngest_inst) 536{ 537 assert(loads == 0 || loadQueue[loadHead]); 538 539 while (loads != 0 && loadQueue[loadHead]->seqNum <= youngest_inst) { 540 commitLoad(); 541 } 542} 543 544template <class Impl> 545void 546LSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst) 547{ 548 assert(stores == 0 || storeQueue[storeHead].inst); 549 550 int store_idx = storeHead; 551 552 while (store_idx != storeTail) { 553 assert(storeQueue[store_idx].inst); 554 // Mark any stores that are now committed and have not yet 555 // been marked as able to write back. 556 if (!storeQueue[store_idx].canWB) { 557 if (storeQueue[store_idx].inst->seqNum > youngest_inst) { 558 break; 559 } 560 DPRINTF(LSQUnit, "Marking store as able to write back, PC " 561 "%#x [sn:%lli]\n", 562 storeQueue[store_idx].inst->readPC(), 563 storeQueue[store_idx].inst->seqNum); 564 565 storeQueue[store_idx].canWB = true; 566 567 ++storesToWB; 568 } 569 570 incrStIdx(store_idx); 571 } 572} 573 574template <class Impl> 575void 576LSQUnit<Impl>::writebackStores() 577{ 578 while (storesToWB > 0 && 579 storeWBIdx != storeTail && 580 storeQueue[storeWBIdx].inst && 581 storeQueue[storeWBIdx].canWB && 582 usedPorts < cachePorts) { 583 584 // Store didn't write any data so no need to write it back to 585 // memory. 586 if (storeQueue[storeWBIdx].size == 0) { 587 completeStore(storeWBIdx); 588 589 incrStIdx(storeWBIdx); 590 591 continue; 592 } 593 594 if (dcacheInterface && dcacheInterface->isBlocked()) { 595 DPRINTF(LSQUnit, "Unable to write back any more stores, cache" 596 " is blocked!\n"); 597 ++lsqCacheBlocked; 598 break; 599 } 600 601 ++usedPorts; 602 603 if (storeQueue[storeWBIdx].inst->isDataPrefetch()) { 604 incrStIdx(storeWBIdx); 605 606 continue; 607 } 608 609 assert(storeQueue[storeWBIdx].req); 610 assert(!storeQueue[storeWBIdx].committed); 611 612 MemReqPtr req = storeQueue[storeWBIdx].req; 613 storeQueue[storeWBIdx].committed = true; 614 615 req->cmd = Write; 616 req->completionEvent = NULL; 617 req->time = curTick; 618 assert(!req->data); 619 req->data = new uint8_t[64]; 620 memcpy(req->data, (uint8_t *)&storeQueue[storeWBIdx].data, req->size); 621 622 DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x " 623 "to Addr:%#x, data:%#x [sn:%lli]\n", 624 storeWBIdx,storeQueue[storeWBIdx].inst->readPC(), 625 req->paddr, *(req->data), 626 storeQueue[storeWBIdx].inst->seqNum); 627 628 switch(storeQueue[storeWBIdx].size) { 629 case 1: 630 cpu->write(req, (uint8_t &)storeQueue[storeWBIdx].data); 631 break; 632 case 2: 633 cpu->write(req, (uint16_t &)storeQueue[storeWBIdx].data); 634 break; 635 case 4: 636 cpu->write(req, (uint32_t &)storeQueue[storeWBIdx].data); 637 break; 638 case 8: 639 cpu->write(req, (uint64_t &)storeQueue[storeWBIdx].data); 640 break; 641 default: 642 panic("Unexpected store size!\n"); 643 } 644 645 // Stores other than store conditionals are completed at this 646 // time. Mark them as completed and, if we have a checker, 647 // tell it that the instruction is completed. 648 // @todo: Figure out what time I can say stores are complete in 649 // the timing memory. 650 if (!(req->flags & LOCKED)) { 651 storeQueue[storeWBIdx].inst->setCompleted(); 652 if (cpu->checker) { 653 cpu->checker->tick(storeQueue[storeWBIdx].inst); 654 } 655 } 656 657 if (dcacheInterface) { 658 assert(!req->completionEvent); 659 StoreCompletionEvent *store_event = new 660 StoreCompletionEvent(storeWBIdx, NULL, this); 661 req->completionEvent = store_event; 662 663 MemAccessResult result = dcacheInterface->access(req); 664 665 if (isStalled() && 666 storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) { 667 DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] " 668 "load idx:%i\n", 669 stallingStoreIsn, stallingLoadIdx); 670 stalled = false; 671 stallingStoreIsn = 0; 672 iewStage->replayMemInst(loadQueue[stallingLoadIdx]); 673 } 674 675 typename IEW::LdWritebackEvent *wb = NULL; 676 if (req->flags & LOCKED) { 677 // Stx_C should not generate a system port transaction 678 // if it misses in the cache, but that might be hard 679 // to accomplish without explicit cache support. 680 wb = new typename 681 IEW::LdWritebackEvent(storeQueue[storeWBIdx].inst, 682 iewStage); 683 store_event->wbEvent = wb; 684 } 685 686 if (result != MA_HIT && dcacheInterface->doEvents()) { 687 DPRINTF(LSQUnit,"D-Cache Write Miss on idx:%i!\n", 688 storeWBIdx); 689 690 DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n", 691 storeQueue[storeWBIdx].inst->seqNum); 692 693 //mshrSeqNums.push_back(storeQueue[storeWBIdx].inst->seqNum); 694 695 //DPRINTF(LSQUnit, "Added MSHR. count = %i\n",mshrSeqNums.size()); 696 697 // @todo: Increment stat here. 698 } else { 699 DPRINTF(LSQUnit,"D-Cache: Write Hit on idx:%i !\n", 700 storeWBIdx); 701 702 DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n", 703 storeQueue[storeWBIdx].inst->seqNum); 704 } 705 706 incrStIdx(storeWBIdx); 707 } else { 708 panic("Must HAVE DCACHE!!!!!\n"); 709 } 710 } 711 712 // Not sure this should set it to 0. 713 usedPorts = 0; 714 715 assert(stores >= 0 && storesToWB >= 0); 716} 717 718/*template <class Impl> 719void 720LSQUnit<Impl>::removeMSHR(InstSeqNum seqNum) 721{ 722 list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(), 723 mshrSeqNums.end(), 724 seqNum); 725 726 if (mshr_it != mshrSeqNums.end()) { 727 mshrSeqNums.erase(mshr_it); 728 DPRINTF(LSQUnit, "Removing MSHR. count = %i\n",mshrSeqNums.size()); 729 } 730}*/ 731 732template <class Impl> 733void 734LSQUnit<Impl>::squash(const InstSeqNum &squashed_num) 735{ 736 DPRINTF(LSQUnit, "Squashing until [sn:%lli]!" 737 "(Loads:%i Stores:%i)\n", squashed_num, loads, stores); 738 739 int load_idx = loadTail; 740 decrLdIdx(load_idx); 741 742 while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) { 743 DPRINTF(LSQUnit,"Load Instruction PC %#x squashed, " 744 "[sn:%lli]\n", 745 loadQueue[load_idx]->readPC(), 746 loadQueue[load_idx]->seqNum); 747 748 if (isStalled() && load_idx == stallingLoadIdx) { 749 stalled = false; 750 stallingStoreIsn = 0; 751 stallingLoadIdx = 0; 752 } 753 754 // Clear the smart pointer to make sure it is decremented. 755 loadQueue[load_idx]->setSquashed(); 756 loadQueue[load_idx] = NULL; 757 --loads; 758 759 // Inefficient! 760 loadTail = load_idx; 761 762 decrLdIdx(load_idx); 763 } 764 765 if (isLoadBlocked) { 766 if (squashed_num < blockedLoadSeqNum) { 767 isLoadBlocked = false; 768 loadBlockedHandled = false; 769 blockedLoadSeqNum = 0; 770 } 771 } 772 773 int store_idx = storeTail; 774 decrStIdx(store_idx); 775 776 while (stores != 0 && 777 storeQueue[store_idx].inst->seqNum > squashed_num) { 778 // Instructions marked as can WB are already committed. 779 if (storeQueue[store_idx].canWB) { 780 break; 781 } 782 783 DPRINTF(LSQUnit,"Store Instruction PC %#x squashed, " 784 "idx:%i [sn:%lli]\n", 785 storeQueue[store_idx].inst->readPC(), 786 store_idx, storeQueue[store_idx].inst->seqNum); 787 788 // I don't think this can happen. It should have been cleared 789 // by the stalling load. 790 if (isStalled() && 791 storeQueue[store_idx].inst->seqNum == stallingStoreIsn) { 792 panic("Is stalled should have been cleared by stalling load!\n"); 793 stalled = false; 794 stallingStoreIsn = 0; 795 } 796 797 // Clear the smart pointer to make sure it is decremented. 798 storeQueue[store_idx].inst->setSquashed(); 799 storeQueue[store_idx].inst = NULL; 800 storeQueue[store_idx].canWB = 0; 801 802 if (storeQueue[store_idx].req) { 803 // There should not be a completion event if the store has 804 // not yet committed. 805 assert(!storeQueue[store_idx].req->completionEvent); 806 } 807 808 storeQueue[store_idx].req = NULL; 809 --stores; 810 811 // Inefficient! 812 storeTail = store_idx; 813 814 decrStIdx(store_idx); 815 ++lsqSquashedStores; 816 } 817} 818 819template <class Impl> 820void 821LSQUnit<Impl>::completeStore(int store_idx) 822{ 823 assert(storeQueue[store_idx].inst); 824 storeQueue[store_idx].completed = true; 825 --storesToWB; 826 // A bit conservative because a store completion may not free up entries, 827 // but hopefully avoids two store completions in one cycle from making 828 // the CPU tick twice. 829 cpu->activityThisCycle(); 830 831 if (store_idx == storeHead) { 832 do { 833 incrStIdx(storeHead); 834 835 --stores; 836 } while (storeQueue[storeHead].completed && 837 storeHead != storeTail); 838 839 iewStage->updateLSQNextCycle = true; 840 } 841 842 DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head " 843 "idx:%i\n", 844 storeQueue[store_idx].inst->seqNum, store_idx, storeHead); 845 846 if (isStalled() && 847 storeQueue[store_idx].inst->seqNum == stallingStoreIsn) { 848 DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] " 849 "load idx:%i\n", 850 stallingStoreIsn, stallingLoadIdx); 851 stalled = false; 852 stallingStoreIsn = 0; 853 iewStage->replayMemInst(loadQueue[stallingLoadIdx]); 854 } 855 856 storeQueue[store_idx].inst->setCompleted(); 857 858 // Tell the checker we've completed this instruction. Some stores 859 // may get reported twice to the checker, but the checker can 860 // handle that case. 861 if (cpu->checker) { 862 cpu->checker->tick(storeQueue[store_idx].inst); 863 } 864} 865 866template <class Impl> 867inline void 868LSQUnit<Impl>::incrStIdx(int &store_idx) 869{ 870 if (++store_idx >= SQEntries) 871 store_idx = 0; 872} 873 874template <class Impl> 875inline void 876LSQUnit<Impl>::decrStIdx(int &store_idx) 877{ 878 if (--store_idx < 0) 879 store_idx += SQEntries; 880} 881 882template <class Impl> 883inline void 884LSQUnit<Impl>::incrLdIdx(int &load_idx) 885{ 886 if (++load_idx >= LQEntries) 887 load_idx = 0; 888} 889 890template <class Impl> 891inline void 892LSQUnit<Impl>::decrLdIdx(int &load_idx) 893{ 894 if (--load_idx < 0) 895 load_idx += LQEntries; 896} 897 898template <class Impl> 899void 900LSQUnit<Impl>::dumpInsts() 901{ 902 cprintf("Load store queue: Dumping instructions.\n"); 903 cprintf("Load queue size: %i\n", loads); 904 cprintf("Load queue: "); 905 906 int load_idx = loadHead; 907 908 while (load_idx != loadTail && loadQueue[load_idx]) { 909 cprintf("%#x ", loadQueue[load_idx]->readPC()); 910 911 incrLdIdx(load_idx); 912 } 913 914 cprintf("Store queue size: %i\n", stores); 915 cprintf("Store queue: "); 916 917 int store_idx = storeHead; 918 919 while (store_idx != storeTail && storeQueue[store_idx].inst) { 920 cprintf("%#x ", storeQueue[store_idx].inst->readPC()); 921 922 incrStIdx(store_idx); 923 } 924 925 cprintf("\n"); 926} 927