lsq_unit_impl.hh revision 2820
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 * Authors: Kevin Lim 29 * Korey Sewell 30 */ 31 32#include "config/use_checker.hh" 33 34#include "cpu/o3/lsq_unit.hh" 35#include "base/str.hh" 36#include "mem/packet.hh" 37#include "mem/request.hh" 38 39#if USE_CHECKER 40#include "cpu/checker/cpu.hh" 41#endif 42 43template<class Impl> 44LSQUnit<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst, PacketPtr _pkt, 45 LSQUnit *lsq_ptr) 46 : Event(&mainEventQueue), inst(_inst), pkt(_pkt), lsqPtr(lsq_ptr) 47{ 48 this->setFlags(Event::AutoDelete); 49} 50 51template<class Impl> 52void 53LSQUnit<Impl>::WritebackEvent::process() 54{ 55 if (!lsqPtr->isSwitchedOut()) { 56 lsqPtr->writeback(inst, pkt); 57 } 58 delete pkt; 59} 60 61template<class Impl> 62const char * 63LSQUnit<Impl>::WritebackEvent::description() 64{ 65 return "Store writeback event"; 66} 67 68template<class Impl> 69void 70LSQUnit<Impl>::completeDataAccess(PacketPtr pkt) 71{ 72 LSQSenderState *state = dynamic_cast<LSQSenderState *>(pkt->senderState); 73 DynInstPtr inst = state->inst; 74 DPRINTF(IEW, "Writeback event [sn:%lli]\n", inst->seqNum); 75 DPRINTF(Activity, "Activity: Writeback event [sn:%lli]\n", inst->seqNum); 76 77 //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum); 78 79 if (isSwitchedOut() || inst->isSquashed()) { 80 iewStage->decrWb(inst->seqNum); 81 delete state; 82 delete pkt; 83 return; 84 } else { 85 if (!state->noWB) { 86 writeback(inst, pkt); 87 } 88 89 if (inst->isStore()) { 90 completeStore(state->idx); 91 } 92 } 93 94 delete state; 95 delete pkt; 96} 97 98template <class Impl> 99Tick 100LSQUnit<Impl>::DcachePort::recvAtomic(PacketPtr pkt) 101{ 102 panic("O3CPU model does not work with atomic mode!"); 103 return curTick; 104} 105 106template <class Impl> 107void 108LSQUnit<Impl>::DcachePort::recvFunctional(PacketPtr pkt) 109{ 110 panic("O3CPU doesn't expect recvFunctional callback!"); 111} 112 113template <class Impl> 114void 115LSQUnit<Impl>::DcachePort::recvStatusChange(Status status) 116{ 117 if (status == RangeChange) 118 return; 119 120 panic("O3CPU doesn't expect recvStatusChange callback!"); 121} 122 123template <class Impl> 124bool 125LSQUnit<Impl>::DcachePort::recvTiming(PacketPtr pkt) 126{ 127 lsq->completeDataAccess(pkt); 128 return true; 129} 130 131template <class Impl> 132void 133LSQUnit<Impl>::DcachePort::recvRetry() 134{ 135 lsq->recvRetry(); 136} 137 138template <class Impl> 139LSQUnit<Impl>::LSQUnit() 140 : loads(0), stores(0), storesToWB(0), stalled(false), 141 isStoreBlocked(false), isLoadBlocked(false), 142 loadBlockedHandled(false) 143{ 144} 145 146template<class Impl> 147void 148LSQUnit<Impl>::init(Params *params, unsigned maxLQEntries, 149 unsigned maxSQEntries, unsigned id) 150{ 151 DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id); 152 153 switchedOut = false; 154 155 lsqID = id; 156 157 // Add 1 for the sentinel entry (they are circular queues). 158 LQEntries = maxLQEntries + 1; 159 SQEntries = maxSQEntries + 1; 160 161 loadQueue.resize(LQEntries); 162 storeQueue.resize(SQEntries); 163 164 loadHead = loadTail = 0; 165 166 storeHead = storeWBIdx = storeTail = 0; 167 168 usedPorts = 0; 169 cachePorts = params->cachePorts; 170 171 mem = params->mem; 172 173 memDepViolator = NULL; 174 175 blockedLoadSeqNum = 0; 176} 177 178template<class Impl> 179void 180LSQUnit<Impl>::setCPU(O3CPU *cpu_ptr) 181{ 182 cpu = cpu_ptr; 183 dcachePort = new DcachePort(cpu, this); 184 185 Port *mem_dport = mem->getPort(""); 186 dcachePort->setPeer(mem_dport); 187 mem_dport->setPeer(dcachePort); 188 189#if USE_CHECKER 190 if (cpu->checker) { 191 cpu->checker->setDcachePort(dcachePort); 192 } 193#endif 194} 195 196template<class Impl> 197std::string 198LSQUnit<Impl>::name() const 199{ 200 if (Impl::MaxThreads == 1) { 201 return iewStage->name() + ".lsq"; 202 } else { 203 return iewStage->name() + ".lsq.thread." + to_string(lsqID); 204 } 205} 206 207template<class Impl> 208void 209LSQUnit<Impl>::regStats() 210{ 211 lsqForwLoads 212 .name(name() + ".forwLoads") 213 .desc("Number of loads that had data forwarded from stores"); 214 215 invAddrLoads 216 .name(name() + ".invAddrLoads") 217 .desc("Number of loads ignored due to an invalid address"); 218 219 lsqSquashedLoads 220 .name(name() + ".squashedLoads") 221 .desc("Number of loads squashed"); 222 223 lsqIgnoredResponses 224 .name(name() + ".ignoredResponses") 225 .desc("Number of memory responses ignored because the instruction is squashed"); 226 227 lsqSquashedStores 228 .name(name() + ".squashedStores") 229 .desc("Number of stores squashed"); 230 231 invAddrSwpfs 232 .name(name() + ".invAddrSwpfs") 233 .desc("Number of software prefetches ignored due to an invalid address"); 234 235 lsqBlockedLoads 236 .name(name() + ".blockedLoads") 237 .desc("Number of blocked loads due to partial load-store forwarding"); 238 239 lsqRescheduledLoads 240 .name(name() + ".rescheduledLoads") 241 .desc("Number of loads that were rescheduled"); 242 243 lsqCacheBlocked 244 .name(name() + ".cacheBlocked") 245 .desc("Number of times an access to memory failed due to the cache being blocked"); 246} 247 248template<class Impl> 249void 250LSQUnit<Impl>::clearLQ() 251{ 252 loadQueue.clear(); 253} 254 255template<class Impl> 256void 257LSQUnit<Impl>::clearSQ() 258{ 259 storeQueue.clear(); 260} 261 262template<class Impl> 263void 264LSQUnit<Impl>::switchOut() 265{ 266 switchedOut = true; 267 for (int i = 0; i < loadQueue.size(); ++i) 268 loadQueue[i] = NULL; 269 270 assert(storesToWB == 0); 271} 272 273template<class Impl> 274void 275LSQUnit<Impl>::takeOverFrom() 276{ 277 switchedOut = false; 278 loads = stores = storesToWB = 0; 279 280 loadHead = loadTail = 0; 281 282 storeHead = storeWBIdx = storeTail = 0; 283 284 usedPorts = 0; 285 286 memDepViolator = NULL; 287 288 blockedLoadSeqNum = 0; 289 290 stalled = false; 291 isLoadBlocked = false; 292 loadBlockedHandled = false; 293} 294 295template<class Impl> 296void 297LSQUnit<Impl>::resizeLQ(unsigned size) 298{ 299 unsigned size_plus_sentinel = size + 1; 300 assert(size_plus_sentinel >= LQEntries); 301 302 if (size_plus_sentinel > LQEntries) { 303 while (size_plus_sentinel > loadQueue.size()) { 304 DynInstPtr dummy; 305 loadQueue.push_back(dummy); 306 LQEntries++; 307 } 308 } else { 309 LQEntries = size_plus_sentinel; 310 } 311 312} 313 314template<class Impl> 315void 316LSQUnit<Impl>::resizeSQ(unsigned size) 317{ 318 unsigned size_plus_sentinel = size + 1; 319 if (size_plus_sentinel > SQEntries) { 320 while (size_plus_sentinel > storeQueue.size()) { 321 SQEntry dummy; 322 storeQueue.push_back(dummy); 323 SQEntries++; 324 } 325 } else { 326 SQEntries = size_plus_sentinel; 327 } 328} 329 330template <class Impl> 331void 332LSQUnit<Impl>::insert(DynInstPtr &inst) 333{ 334 assert(inst->isMemRef()); 335 336 assert(inst->isLoad() || inst->isStore()); 337 338 if (inst->isLoad()) { 339 insertLoad(inst); 340 } else { 341 insertStore(inst); 342 } 343 344 inst->setInLSQ(); 345} 346 347template <class Impl> 348void 349LSQUnit<Impl>::insertLoad(DynInstPtr &load_inst) 350{ 351 assert((loadTail + 1) % LQEntries != loadHead); 352 assert(loads < LQEntries); 353 354 DPRINTF(LSQUnit, "Inserting load PC %#x, idx:%i [sn:%lli]\n", 355 load_inst->readPC(), loadTail, load_inst->seqNum); 356 357 load_inst->lqIdx = loadTail; 358 359 if (stores == 0) { 360 load_inst->sqIdx = -1; 361 } else { 362 load_inst->sqIdx = storeTail; 363 } 364 365 loadQueue[loadTail] = load_inst; 366 367 incrLdIdx(loadTail); 368 369 ++loads; 370} 371 372template <class Impl> 373void 374LSQUnit<Impl>::insertStore(DynInstPtr &store_inst) 375{ 376 // Make sure it is not full before inserting an instruction. 377 assert((storeTail + 1) % SQEntries != storeHead); 378 assert(stores < SQEntries); 379 380 DPRINTF(LSQUnit, "Inserting store PC %#x, idx:%i [sn:%lli]\n", 381 store_inst->readPC(), storeTail, store_inst->seqNum); 382 383 store_inst->sqIdx = storeTail; 384 store_inst->lqIdx = loadTail; 385 386 storeQueue[storeTail] = SQEntry(store_inst); 387 388 incrStIdx(storeTail); 389 390 ++stores; 391} 392 393template <class Impl> 394typename Impl::DynInstPtr 395LSQUnit<Impl>::getMemDepViolator() 396{ 397 DynInstPtr temp = memDepViolator; 398 399 memDepViolator = NULL; 400 401 return temp; 402} 403 404template <class Impl> 405unsigned 406LSQUnit<Impl>::numFreeEntries() 407{ 408 unsigned free_lq_entries = LQEntries - loads; 409 unsigned free_sq_entries = SQEntries - stores; 410 411 // Both the LQ and SQ entries have an extra dummy entry to differentiate 412 // empty/full conditions. Subtract 1 from the free entries. 413 if (free_lq_entries < free_sq_entries) { 414 return free_lq_entries - 1; 415 } else { 416 return free_sq_entries - 1; 417 } 418} 419 420template <class Impl> 421int 422LSQUnit<Impl>::numLoadsReady() 423{ 424 int load_idx = loadHead; 425 int retval = 0; 426 427 while (load_idx != loadTail) { 428 assert(loadQueue[load_idx]); 429 430 if (loadQueue[load_idx]->readyToIssue()) { 431 ++retval; 432 } 433 } 434 435 return retval; 436} 437 438template <class Impl> 439Fault 440LSQUnit<Impl>::executeLoad(DynInstPtr &inst) 441{ 442 // Execute a specific load. 443 Fault load_fault = NoFault; 444 445 DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n", 446 inst->readPC(),inst->seqNum); 447 448 load_fault = inst->initiateAcc(); 449 450 // If the instruction faulted, then we need to send it along to commit 451 // without the instruction completing. 452 if (load_fault != NoFault) { 453 // Send this instruction to commit, also make sure iew stage 454 // realizes there is activity. 455 iewStage->instToCommit(inst); 456 iewStage->activityThisCycle(); 457 } 458 459 return load_fault; 460} 461 462template <class Impl> 463Fault 464LSQUnit<Impl>::executeStore(DynInstPtr &store_inst) 465{ 466 using namespace TheISA; 467 // Make sure that a store exists. 468 assert(stores != 0); 469 470 int store_idx = store_inst->sqIdx; 471 472 DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n", 473 store_inst->readPC(), store_inst->seqNum); 474 475 // Check the recently completed loads to see if any match this store's 476 // address. If so, then we have a memory ordering violation. 477 int load_idx = store_inst->lqIdx; 478 479 Fault store_fault = store_inst->initiateAcc(); 480 481 if (storeQueue[store_idx].size == 0) { 482 DPRINTF(LSQUnit,"Fault on Store PC %#x, [sn:%lli],Size = 0\n", 483 store_inst->readPC(),store_inst->seqNum); 484 485 return store_fault; 486 } 487 488 assert(store_fault == NoFault); 489 490 if (store_inst->isStoreConditional()) { 491 // Store conditionals need to set themselves as able to 492 // writeback if we haven't had a fault by here. 493 storeQueue[store_idx].canWB = true; 494 495 ++storesToWB; 496 } 497 498 if (!memDepViolator) { 499 while (load_idx != loadTail) { 500 // Really only need to check loads that have actually executed 501 // It's safe to check all loads because effAddr is set to 502 // InvalAddr when the dyn inst is created. 503 504 // @todo: For now this is extra conservative, detecting a 505 // violation if the addresses match assuming all accesses 506 // are quad word accesses. 507 508 // @todo: Fix this, magic number being used here 509 if ((loadQueue[load_idx]->effAddr >> 8) == 510 (store_inst->effAddr >> 8)) { 511 // A load incorrectly passed this store. Squash and refetch. 512 // For now return a fault to show that it was unsuccessful. 513 memDepViolator = loadQueue[load_idx]; 514 515 return genMachineCheckFault(); 516 } 517 518 incrLdIdx(load_idx); 519 } 520 521 // If we've reached this point, there was no violation. 522 memDepViolator = NULL; 523 } 524 525 return store_fault; 526} 527 528template <class Impl> 529void 530LSQUnit<Impl>::commitLoad() 531{ 532 assert(loadQueue[loadHead]); 533 534 DPRINTF(LSQUnit, "Committing head load instruction, PC %#x\n", 535 loadQueue[loadHead]->readPC()); 536 537 loadQueue[loadHead] = NULL; 538 539 incrLdIdx(loadHead); 540 541 --loads; 542} 543 544template <class Impl> 545void 546LSQUnit<Impl>::commitLoads(InstSeqNum &youngest_inst) 547{ 548 assert(loads == 0 || loadQueue[loadHead]); 549 550 while (loads != 0 && loadQueue[loadHead]->seqNum <= youngest_inst) { 551 commitLoad(); 552 } 553} 554 555template <class Impl> 556void 557LSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst) 558{ 559 assert(stores == 0 || storeQueue[storeHead].inst); 560 561 int store_idx = storeHead; 562 563 while (store_idx != storeTail) { 564 assert(storeQueue[store_idx].inst); 565 // Mark any stores that are now committed and have not yet 566 // been marked as able to write back. 567 if (!storeQueue[store_idx].canWB) { 568 if (storeQueue[store_idx].inst->seqNum > youngest_inst) { 569 break; 570 } 571 DPRINTF(LSQUnit, "Marking store as able to write back, PC " 572 "%#x [sn:%lli]\n", 573 storeQueue[store_idx].inst->readPC(), 574 storeQueue[store_idx].inst->seqNum); 575 576 storeQueue[store_idx].canWB = true; 577 578 ++storesToWB; 579 } 580 581 incrStIdx(store_idx); 582 } 583} 584 585template <class Impl> 586void 587LSQUnit<Impl>::writebackStores() 588{ 589 while (storesToWB > 0 && 590 storeWBIdx != storeTail && 591 storeQueue[storeWBIdx].inst && 592 storeQueue[storeWBIdx].canWB && 593 usedPorts < cachePorts) { 594 595 if (isStoreBlocked) { 596 DPRINTF(LSQUnit, "Unable to write back any more stores, cache" 597 " is blocked!\n"); 598 break; 599 } 600 601 // Store didn't write any data so no need to write it back to 602 // memory. 603 if (storeQueue[storeWBIdx].size == 0) { 604 completeStore(storeWBIdx); 605 606 incrStIdx(storeWBIdx); 607 608 continue; 609 } 610 611 ++usedPorts; 612 613 if (storeQueue[storeWBIdx].inst->isDataPrefetch()) { 614 incrStIdx(storeWBIdx); 615 616 continue; 617 } 618 619 assert(storeQueue[storeWBIdx].req); 620 assert(!storeQueue[storeWBIdx].committed); 621 622 DynInstPtr inst = storeQueue[storeWBIdx].inst; 623 624 Request *req = storeQueue[storeWBIdx].req; 625 storeQueue[storeWBIdx].committed = true; 626 627 assert(!inst->memData); 628 inst->memData = new uint8_t[64]; 629 memcpy(inst->memData, (uint8_t *)&storeQueue[storeWBIdx].data, 630 req->getSize()); 631 632 PacketPtr data_pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast); 633 data_pkt->dataStatic(inst->memData); 634 635 LSQSenderState *state = new LSQSenderState; 636 state->isLoad = false; 637 state->idx = storeWBIdx; 638 state->inst = inst; 639 data_pkt->senderState = state; 640 641 DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x " 642 "to Addr:%#x, data:%#x [sn:%lli]\n", 643 storeWBIdx, storeQueue[storeWBIdx].inst->readPC(), 644 req->getPaddr(), *(inst->memData), 645 storeQueue[storeWBIdx].inst->seqNum); 646 647 // @todo: Remove this SC hack once the memory system handles it. 648 if (req->getFlags() & LOCKED) { 649 if (req->getFlags() & UNCACHEABLE) { 650 req->setScResult(2); 651 } else { 652 if (cpu->lockFlag) { 653 req->setScResult(1); 654 } else { 655 req->setScResult(0); 656 // Hack: Instantly complete this store. 657 completeDataAccess(data_pkt); 658 incrStIdx(storeWBIdx); 659 continue; 660 } 661 } 662 } else { 663 // Non-store conditionals do not need a writeback. 664 state->noWB = true; 665 } 666 667 if (!dcachePort->sendTiming(data_pkt)) { 668 // Need to handle becoming blocked on a store. 669 isStoreBlocked = true; 670 ++lsqCacheBlocked; 671 assert(retryPkt == NULL); 672 retryPkt = data_pkt; 673 } else { 674 storePostSend(data_pkt); 675 } 676 } 677 678 // Not sure this should set it to 0. 679 usedPorts = 0; 680 681 assert(stores >= 0 && storesToWB >= 0); 682} 683 684/*template <class Impl> 685void 686LSQUnit<Impl>::removeMSHR(InstSeqNum seqNum) 687{ 688 list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(), 689 mshrSeqNums.end(), 690 seqNum); 691 692 if (mshr_it != mshrSeqNums.end()) { 693 mshrSeqNums.erase(mshr_it); 694 DPRINTF(LSQUnit, "Removing MSHR. count = %i\n",mshrSeqNums.size()); 695 } 696}*/ 697 698template <class Impl> 699void 700LSQUnit<Impl>::squash(const InstSeqNum &squashed_num) 701{ 702 DPRINTF(LSQUnit, "Squashing until [sn:%lli]!" 703 "(Loads:%i Stores:%i)\n", squashed_num, loads, stores); 704 705 int load_idx = loadTail; 706 decrLdIdx(load_idx); 707 708 while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) { 709 DPRINTF(LSQUnit,"Load Instruction PC %#x squashed, " 710 "[sn:%lli]\n", 711 loadQueue[load_idx]->readPC(), 712 loadQueue[load_idx]->seqNum); 713 714 if (isStalled() && load_idx == stallingLoadIdx) { 715 stalled = false; 716 stallingStoreIsn = 0; 717 stallingLoadIdx = 0; 718 } 719 720 // Clear the smart pointer to make sure it is decremented. 721 loadQueue[load_idx]->setSquashed(); 722 loadQueue[load_idx] = NULL; 723 --loads; 724 725 // Inefficient! 726 loadTail = load_idx; 727 728 decrLdIdx(load_idx); 729 ++lsqSquashedLoads; 730 } 731 732 if (isLoadBlocked) { 733 if (squashed_num < blockedLoadSeqNum) { 734 isLoadBlocked = false; 735 loadBlockedHandled = false; 736 blockedLoadSeqNum = 0; 737 } 738 } 739 740 int store_idx = storeTail; 741 decrStIdx(store_idx); 742 743 while (stores != 0 && 744 storeQueue[store_idx].inst->seqNum > squashed_num) { 745 // Instructions marked as can WB are already committed. 746 if (storeQueue[store_idx].canWB) { 747 break; 748 } 749 750 DPRINTF(LSQUnit,"Store Instruction PC %#x squashed, " 751 "idx:%i [sn:%lli]\n", 752 storeQueue[store_idx].inst->readPC(), 753 store_idx, storeQueue[store_idx].inst->seqNum); 754 755 // I don't think this can happen. It should have been cleared 756 // by the stalling load. 757 if (isStalled() && 758 storeQueue[store_idx].inst->seqNum == stallingStoreIsn) { 759 panic("Is stalled should have been cleared by stalling load!\n"); 760 stalled = false; 761 stallingStoreIsn = 0; 762 } 763 764 // Clear the smart pointer to make sure it is decremented. 765 storeQueue[store_idx].inst->setSquashed(); 766 storeQueue[store_idx].inst = NULL; 767 storeQueue[store_idx].canWB = 0; 768 769 storeQueue[store_idx].req = NULL; 770 --stores; 771 772 // Inefficient! 773 storeTail = store_idx; 774 775 decrStIdx(store_idx); 776 ++lsqSquashedStores; 777 } 778} 779 780template <class Impl> 781void 782LSQUnit<Impl>::storePostSend(Packet *pkt) 783{ 784 if (isStalled() && 785 storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) { 786 DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] " 787 "load idx:%i\n", 788 stallingStoreIsn, stallingLoadIdx); 789 stalled = false; 790 stallingStoreIsn = 0; 791 iewStage->replayMemInst(loadQueue[stallingLoadIdx]); 792 } 793 794 if (!storeQueue[storeWBIdx].inst->isStoreConditional()) { 795 // The store is basically completed at this time. This 796 // only works so long as the checker doesn't try to 797 // verify the value in memory for stores. 798 storeQueue[storeWBIdx].inst->setCompleted(); 799#if USE_CHECKER 800 if (cpu->checker) { 801 cpu->checker->verify(storeQueue[storeWBIdx].inst); 802 } 803#endif 804 } 805 806 if (pkt->result != Packet::Success) { 807 DPRINTF(LSQUnit,"D-Cache Write Miss on idx:%i!\n", 808 storeWBIdx); 809 810 DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n", 811 storeQueue[storeWBIdx].inst->seqNum); 812 813 //mshrSeqNums.push_back(storeQueue[storeWBIdx].inst->seqNum); 814 815 //DPRINTF(LSQUnit, "Added MSHR. count = %i\n",mshrSeqNums.size()); 816 817 // @todo: Increment stat here. 818 } else { 819 DPRINTF(LSQUnit,"D-Cache: Write Hit on idx:%i !\n", 820 storeWBIdx); 821 822 DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n", 823 storeQueue[storeWBIdx].inst->seqNum); 824 } 825 826 incrStIdx(storeWBIdx); 827} 828 829template <class Impl> 830void 831LSQUnit<Impl>::writeback(DynInstPtr &inst, PacketPtr pkt) 832{ 833 iewStage->wakeCPU(); 834 835 // Squashed instructions do not need to complete their access. 836 if (inst->isSquashed()) { 837 assert(!inst->isStore()); 838 ++lsqIgnoredResponses; 839 return; 840 } 841 842 if (!inst->isExecuted()) { 843 inst->setExecuted(); 844 845 // Complete access to copy data to proper place. 846 inst->completeAcc(pkt); 847 } 848 849 // Need to insert instruction into queue to commit 850 iewStage->instToCommit(inst); 851 852 iewStage->activityThisCycle(); 853} 854 855template <class Impl> 856void 857LSQUnit<Impl>::completeStore(int store_idx) 858{ 859 assert(storeQueue[store_idx].inst); 860 storeQueue[store_idx].completed = true; 861 --storesToWB; 862 // A bit conservative because a store completion may not free up entries, 863 // but hopefully avoids two store completions in one cycle from making 864 // the CPU tick twice. 865 cpu->activityThisCycle(); 866 867 if (store_idx == storeHead) { 868 do { 869 incrStIdx(storeHead); 870 871 --stores; 872 } while (storeQueue[storeHead].completed && 873 storeHead != storeTail); 874 875 iewStage->updateLSQNextCycle = true; 876 } 877 878 DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head " 879 "idx:%i\n", 880 storeQueue[store_idx].inst->seqNum, store_idx, storeHead); 881 882 if (isStalled() && 883 storeQueue[store_idx].inst->seqNum == stallingStoreIsn) { 884 DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] " 885 "load idx:%i\n", 886 stallingStoreIsn, stallingLoadIdx); 887 stalled = false; 888 stallingStoreIsn = 0; 889 iewStage->replayMemInst(loadQueue[stallingLoadIdx]); 890 } 891 892 storeQueue[store_idx].inst->setCompleted(); 893 894 // Tell the checker we've completed this instruction. Some stores 895 // may get reported twice to the checker, but the checker can 896 // handle that case. 897#if USE_CHECKER 898 if (cpu->checker) { 899 cpu->checker->verify(storeQueue[store_idx].inst); 900 } 901#endif 902} 903 904template <class Impl> 905void 906LSQUnit<Impl>::recvRetry() 907{ 908 if (isStoreBlocked) { 909 assert(retryPkt != NULL); 910 911 if (dcachePort->sendTiming(retryPkt)) { 912 storePostSend(retryPkt); 913 retryPkt = NULL; 914 isStoreBlocked = false; 915 } else { 916 // Still blocked! 917 ++lsqCacheBlocked; 918 } 919 } else if (isLoadBlocked) { 920 DPRINTF(LSQUnit, "Loads squash themselves and all younger insts, " 921 "no need to resend packet.\n"); 922 } else { 923 DPRINTF(LSQUnit, "Retry received but LSQ is no longer blocked.\n"); 924 } 925} 926 927template <class Impl> 928inline void 929LSQUnit<Impl>::incrStIdx(int &store_idx) 930{ 931 if (++store_idx >= SQEntries) 932 store_idx = 0; 933} 934 935template <class Impl> 936inline void 937LSQUnit<Impl>::decrStIdx(int &store_idx) 938{ 939 if (--store_idx < 0) 940 store_idx += SQEntries; 941} 942 943template <class Impl> 944inline void 945LSQUnit<Impl>::incrLdIdx(int &load_idx) 946{ 947 if (++load_idx >= LQEntries) 948 load_idx = 0; 949} 950 951template <class Impl> 952inline void 953LSQUnit<Impl>::decrLdIdx(int &load_idx) 954{ 955 if (--load_idx < 0) 956 load_idx += LQEntries; 957} 958 959template <class Impl> 960void 961LSQUnit<Impl>::dumpInsts() 962{ 963 cprintf("Load store queue: Dumping instructions.\n"); 964 cprintf("Load queue size: %i\n", loads); 965 cprintf("Load queue: "); 966 967 int load_idx = loadHead; 968 969 while (load_idx != loadTail && loadQueue[load_idx]) { 970 cprintf("%#x ", loadQueue[load_idx]->readPC()); 971 972 incrLdIdx(load_idx); 973 } 974 975 cprintf("Store queue size: %i\n", stores); 976 cprintf("Store queue: "); 977 978 int store_idx = storeHead; 979 980 while (store_idx != storeTail && storeQueue[store_idx].inst) { 981 cprintf("%#x ", storeQueue[store_idx].inst->readPC()); 982 983 incrStIdx(store_idx); 984 } 985 986 cprintf("\n"); 987} 988