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