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