lsq_unit.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#ifndef __CPU_O3_LSQ_UNIT_HH__ 30#define __CPU_O3_LSQ_UNIT_HH__ 31 32#include <map> 33#include <queue> 34#include <algorithm> 35 36#include "config/full_system.hh" 37#include "base/hashmap.hh" 38#include "cpu/inst_seq.hh" 39#include "mem/mem_interface.hh" 40//#include "mem/page_table.hh" 41#include "sim/debug.hh" 42#include "sim/sim_object.hh" 43#include "arch/faults.hh" 44 45/** 46 * Class that implements the actual LQ and SQ for each specific thread. 47 * Both are circular queues; load entries are freed upon committing, while 48 * store entries are freed once they writeback. The LSQUnit tracks if there 49 * are memory ordering violations, and also detects partial load to store 50 * forwarding cases (a store only has part of a load's data) that requires 51 * the load to wait until the store writes back. In the former case it 52 * holds onto the instruction until the dependence unit looks at it, and 53 * in the latter it stalls the LSQ until the store writes back. At that 54 * point the load is replayed. 55 */ 56template <class Impl> 57class LSQUnit { 58 protected: 59 typedef TheISA::IntReg IntReg; 60 public: 61 typedef typename Impl::Params Params; 62 typedef typename Impl::FullCPU FullCPU; 63 typedef typename Impl::DynInstPtr DynInstPtr; 64 typedef typename Impl::CPUPol::IEW IEW; 65 typedef typename Impl::CPUPol::IssueStruct IssueStruct; 66 67 private: 68 class StoreCompletionEvent : public Event { 69 public: 70 /** Constructs a store completion event. */ 71 StoreCompletionEvent(int store_idx, Event *wb_event, LSQUnit *lsq_ptr); 72 73 /** Processes the store completion event. */ 74 void process(); 75 76 /** Returns the description of this event. */ 77 const char *description(); 78 79 private: 80 /** The store index of the store being written back. */ 81 int storeIdx; 82 /** The writeback event for the store. Needed for store 83 * conditionals. 84 */ 85 Event *wbEvent; 86 /** The pointer to the LSQ unit that issued the store. */ 87 LSQUnit<Impl> *lsqPtr; 88 }; 89 90 friend class StoreCompletionEvent; 91 92 public: 93 /** Constructs an LSQ unit. init() must be called prior to use. */ 94 LSQUnit(); 95 96 /** Initializes the LSQ unit with the specified number of entries. */ 97 void init(Params *params, unsigned maxLQEntries, 98 unsigned maxSQEntries, unsigned id); 99 100 /** Returns the name of the LSQ unit. */ 101 std::string name() const; 102 103 /** Sets the CPU pointer. */ 104 void setCPU(FullCPU *cpu_ptr) 105 { cpu = cpu_ptr; } 106 107 /** Sets the IEW stage pointer. */ 108 void setIEW(IEW *iew_ptr) 109 { iewStage = iew_ptr; } 110 111 /** Sets the page table pointer. */ 112// void setPageTable(PageTable *pt_ptr); 113 114 void switchOut(); 115 116 void takeOverFrom(); 117 118 bool isSwitchedOut() { return switchedOut; } 119 120 /** Ticks the LSQ unit, which in this case only resets the number of 121 * used cache ports. 122 * @todo: Move the number of used ports up to the LSQ level so it can 123 * be shared by all LSQ units. 124 */ 125 void tick() { usedPorts = 0; } 126 127 /** Inserts an instruction. */ 128 void insert(DynInstPtr &inst); 129 /** Inserts a load instruction. */ 130 void insertLoad(DynInstPtr &load_inst); 131 /** Inserts a store instruction. */ 132 void insertStore(DynInstPtr &store_inst); 133 134 /** Executes a load instruction. */ 135 Fault executeLoad(DynInstPtr &inst); 136 137 Fault executeLoad(int lq_idx); 138 /** Executes a store instruction. */ 139 Fault executeStore(DynInstPtr &inst); 140 141 /** Commits the head load. */ 142 void commitLoad(); 143 /** Commits a specific load, given by the sequence number. */ 144 void commitLoad(InstSeqNum &inst); 145 /** Commits loads older than a specific sequence number. */ 146 void commitLoads(InstSeqNum &youngest_inst); 147 148 /** Commits stores older than a specific sequence number. */ 149 void commitStores(InstSeqNum &youngest_inst); 150 151 /** Writes back stores. */ 152 void writebackStores(); 153 154 // @todo: Include stats in the LSQ unit. 155 //void regStats(); 156 157 /** Clears all the entries in the LQ. */ 158 void clearLQ(); 159 160 /** Clears all the entries in the SQ. */ 161 void clearSQ(); 162 163 /** Resizes the LQ to a given size. */ 164 void resizeLQ(unsigned size); 165 166 /** Resizes the SQ to a given size. */ 167 void resizeSQ(unsigned size); 168 169 /** Squashes all instructions younger than a specific sequence number. */ 170 void squash(const InstSeqNum &squashed_num); 171 172 /** Returns if there is a memory ordering violation. Value is reset upon 173 * call to getMemDepViolator(). 174 */ 175 bool violation() { return memDepViolator; } 176 177 /** Returns the memory ordering violator. */ 178 DynInstPtr getMemDepViolator(); 179 180 /** Returns if a load became blocked due to the memory system. It clears 181 * the bool's value upon this being called. 182 */ 183 bool loadBlocked() 184 { return isLoadBlocked; } 185 186 void clearLoadBlocked() 187 { isLoadBlocked = false; } 188 189 bool isLoadBlockedHandled() 190 { return loadBlockedHandled; } 191 192 void setLoadBlockedHandled() 193 { loadBlockedHandled = true; } 194 195 /** Returns the number of free entries (min of free LQ and SQ entries). */ 196 unsigned numFreeEntries(); 197 198 /** Returns the number of loads ready to execute. */ 199 int numLoadsReady(); 200 201 /** Returns the number of loads in the LQ. */ 202 int numLoads() { return loads; } 203 204 /** Returns the number of stores in the SQ. */ 205 int numStores() { return stores; } 206 207 /** Returns if either the LQ or SQ is full. */ 208 bool isFull() { return lqFull() || sqFull(); } 209 210 /** Returns if the LQ is full. */ 211 bool lqFull() { return loads >= (LQEntries - 1); } 212 213 /** Returns if the SQ is full. */ 214 bool sqFull() { return stores >= (SQEntries - 1); } 215 216 /** Debugging function to dump instructions in the LSQ. */ 217 void dumpInsts(); 218 219 /** Returns the number of instructions in the LSQ. */ 220 unsigned getCount() { return loads + stores; } 221 222 /** Returns if there are any stores to writeback. */ 223 bool hasStoresToWB() { return storesToWB; } 224 225 /** Returns the number of stores to writeback. */ 226 int numStoresToWB() { return storesToWB; } 227 228 /** Returns if the LSQ unit will writeback on this cycle. */ 229 bool willWB() { return storeQueue[storeWBIdx].canWB && 230 !storeQueue[storeWBIdx].completed && 231 !dcacheInterface->isBlocked(); } 232 233 private: 234 /** Completes the store at the specified index. */ 235 void completeStore(int store_idx); 236 237 /** Increments the given store index (circular queue). */ 238 inline void incrStIdx(int &store_idx); 239 /** Decrements the given store index (circular queue). */ 240 inline void decrStIdx(int &store_idx); 241 /** Increments the given load index (circular queue). */ 242 inline void incrLdIdx(int &load_idx); 243 /** Decrements the given load index (circular queue). */ 244 inline void decrLdIdx(int &load_idx); 245 246 private: 247 /** Pointer to the CPU. */ 248 FullCPU *cpu; 249 250 /** Pointer to the IEW stage. */ 251 IEW *iewStage; 252 253 /** Pointer to the D-cache. */ 254 MemInterface *dcacheInterface; 255 256 /** Pointer to the page table. */ 257// PageTable *pTable; 258 259 public: 260 struct SQEntry { 261 /** Constructs an empty store queue entry. */ 262 SQEntry() 263 : inst(NULL), req(NULL), size(0), data(0), 264 canWB(0), committed(0), completed(0) 265 { } 266 267 /** Constructs a store queue entry for a given instruction. */ 268 SQEntry(DynInstPtr &_inst) 269 : inst(_inst), req(NULL), size(0), data(0), 270 canWB(0), committed(0), completed(0) 271 { } 272 273 /** The store instruction. */ 274 DynInstPtr inst; 275 /** The memory request for the store. */ 276 MemReqPtr req; 277 /** The size of the store. */ 278 int size; 279 /** The store data. */ 280 IntReg data; 281 /** Whether or not the store can writeback. */ 282 bool canWB; 283 /** Whether or not the store is committed. */ 284 bool committed; 285 /** Whether or not the store is completed. */ 286 bool completed; 287 }; 288/* 289 enum Status { 290 Running, 291 Idle, 292 DcacheMissStall, 293 DcacheMissSwitch 294 }; 295*/ 296 private: 297 /** The LSQUnit thread id. */ 298 unsigned lsqID; 299 300 /** The status of the LSQ unit. */ 301// Status _status; 302 303 /** The store queue. */ 304 std::vector<SQEntry> storeQueue; 305 306 /** The load queue. */ 307 std::vector<DynInstPtr> loadQueue; 308 309 // Consider making these 16 bits 310 /** The number of LQ entries. */ 311 unsigned LQEntries; 312 /** The number of SQ entries. */ 313 unsigned SQEntries; 314 315 /** The number of load instructions in the LQ. */ 316 int loads; 317 /** The number of store instructions in the SQ (excludes those waiting to 318 * writeback). 319 */ 320 int stores; 321 /** The number of store instructions in the SQ waiting to writeback. */ 322 int storesToWB; 323 324 /** The index of the head instruction in the LQ. */ 325 int loadHead; 326 /** The index of the tail instruction in the LQ. */ 327 int loadTail; 328 329 /** The index of the head instruction in the SQ. */ 330 int storeHead; 331 /** The index of the first instruction that is ready to be written back, 332 * and has not yet been written back. 333 */ 334 int storeWBIdx; 335 /** The index of the tail instruction in the SQ. */ 336 int storeTail; 337 338 /// @todo Consider moving to a more advanced model with write vs read ports 339 /** The number of cache ports available each cycle. */ 340 int cachePorts; 341 342 /** The number of used cache ports in this cycle. */ 343 int usedPorts; 344 345 bool switchedOut; 346 347 //list<InstSeqNum> mshrSeqNums; 348 349 //Stats::Scalar<> dcacheStallCycles; 350 Counter lastDcacheStall; 351 352 /** Wire to read information from the issue stage time queue. */ 353 typename TimeBuffer<IssueStruct>::wire fromIssue; 354 355 // Make these per thread? 356 /** Whether or not the LSQ is stalled. */ 357 bool stalled; 358 /** The store that causes the stall due to partial store to load 359 * forwarding. 360 */ 361 InstSeqNum stallingStoreIsn; 362 /** The index of the above store. */ 363 int stallingLoadIdx; 364 365 /** Whether or not a load is blocked due to the memory system. It is 366 * cleared when this value is checked via loadBlocked(). 367 */ 368 bool isLoadBlocked; 369 370 bool loadBlockedHandled; 371 372 InstSeqNum blockedLoadSeqNum; 373 374 /** The oldest faulting load instruction. */ 375 DynInstPtr loadFaultInst; 376 /** The oldest faulting store instruction. */ 377 DynInstPtr storeFaultInst; 378 379 /** The oldest load that caused a memory ordering violation. */ 380 DynInstPtr memDepViolator; 381 382 // Will also need how many read/write ports the Dcache has. Or keep track 383 // of that in stage that is one level up, and only call executeLoad/Store 384 // the appropriate number of times. 385/* 386 // total number of loads forwaded from LSQ stores 387 Stats::Vector<> lsq_forw_loads; 388 389 // total number of loads ignored due to invalid addresses 390 Stats::Vector<> inv_addr_loads; 391 392 // total number of software prefetches ignored due to invalid addresses 393 Stats::Vector<> inv_addr_swpfs; 394 395 // total non-speculative bogus addresses seen (debug var) 396 Counter sim_invalid_addrs; 397 Stats::Vector<> fu_busy; //cumulative fu busy 398 399 // ready loads blocked due to memory disambiguation 400 Stats::Vector<> lsq_blocked_loads; 401 402 Stats::Scalar<> lsqInversion; 403*/ 404 public: 405 /** Executes the load at the given index. */ 406 template <class T> 407 Fault read(MemReqPtr &req, T &data, int load_idx); 408 409 /** Executes the store at the given index. */ 410 template <class T> 411 Fault write(MemReqPtr &req, T &data, int store_idx); 412 413 /** Returns the index of the head load instruction. */ 414 int getLoadHead() { return loadHead; } 415 /** Returns the sequence number of the head load instruction. */ 416 InstSeqNum getLoadHeadSeqNum() 417 { 418 if (loadQueue[loadHead]) { 419 return loadQueue[loadHead]->seqNum; 420 } else { 421 return 0; 422 } 423 424 } 425 426 /** Returns the index of the head store instruction. */ 427 int getStoreHead() { return storeHead; } 428 /** Returns the sequence number of the head store instruction. */ 429 InstSeqNum getStoreHeadSeqNum() 430 { 431 if (storeQueue[storeHead].inst) { 432 return storeQueue[storeHead].inst->seqNum; 433 } else { 434 return 0; 435 } 436 437 } 438 439 /** Returns whether or not the LSQ unit is stalled. */ 440 bool isStalled() { return stalled; } 441}; 442 443template <class Impl> 444template <class T> 445Fault 446LSQUnit<Impl>::read(MemReqPtr &req, T &data, int load_idx) 447{ 448 //Depending on issue2execute delay a squashed load could 449 //execute if it is found to be squashed in the same 450 //cycle it is scheduled to execute 451 assert(loadQueue[load_idx]); 452 453 if (loadQueue[load_idx]->isExecuted()) { 454 panic("Should not reach this point with split ops!"); 455 memcpy(&data,req->data,req->size); 456 457 return NoFault; 458 } 459 460 // Make sure this isn't an uncacheable access 461 // A bit of a hackish way to get uncached accesses to work only if they're 462 // at the head of the LSQ and are ready to commit (at the head of the ROB 463 // too). 464 // @todo: Fix uncached accesses. 465 if (req->flags & UNCACHEABLE && 466 (load_idx != loadHead || !loadQueue[load_idx]->reachedCommit)) { 467 iewStage->rescheduleMemInst(loadQueue[load_idx]); 468 return TheISA::genMachineCheckFault(); 469 } 470 471 // Check the SQ for any previous stores that might lead to forwarding 472 int store_idx = loadQueue[load_idx]->sqIdx; 473 474 int store_size = 0; 475 476 DPRINTF(LSQUnit, "Read called, load idx: %i, store idx: %i, " 477 "storeHead: %i addr: %#x\n", 478 load_idx, store_idx, storeHead, req->paddr); 479 480#ifdef FULL_SYSTEM 481 if (req->flags & LOCKED) { 482 cpu->lockAddr = req->paddr; 483 cpu->lockFlag = true; 484 } 485#endif 486 487 while (store_idx != -1) { 488 // End once we've reached the top of the LSQ 489 if (store_idx == storeWBIdx) { 490 break; 491 } 492 493 // Move the index to one younger 494 if (--store_idx < 0) 495 store_idx += SQEntries; 496 497 assert(storeQueue[store_idx].inst); 498 499 store_size = storeQueue[store_idx].size; 500 501 if (store_size == 0) 502 continue; 503 504 // Check if the store data is within the lower and upper bounds of 505 // addresses that the request needs. 506 bool store_has_lower_limit = 507 req->vaddr >= storeQueue[store_idx].inst->effAddr; 508 bool store_has_upper_limit = 509 (req->vaddr + req->size) <= (storeQueue[store_idx].inst->effAddr + 510 store_size); 511 bool lower_load_has_store_part = 512 req->vaddr < (storeQueue[store_idx].inst->effAddr + 513 store_size); 514 bool upper_load_has_store_part = 515 (req->vaddr + req->size) > storeQueue[store_idx].inst->effAddr; 516 517 // If the store's data has all of the data needed, we can forward. 518 if (store_has_lower_limit && store_has_upper_limit) { 519 520 int shift_amt = req->vaddr & (store_size - 1); 521 // Assumes byte addressing 522 shift_amt = shift_amt << 3; 523 524 // Cast this to type T? 525 data = storeQueue[store_idx].data >> shift_amt; 526 527 req->cmd = Read; 528 assert(!req->completionEvent); 529 req->completionEvent = NULL; 530 req->time = curTick; 531 assert(!req->data); 532 req->data = new uint8_t[64]; 533 534 memcpy(req->data, &data, req->size); 535 536 DPRINTF(LSQUnit, "Forwarding from store idx %i to load to " 537 "addr %#x, data %#x\n", 538 store_idx, req->vaddr, *(req->data)); 539 540 typename IEW::LdWritebackEvent *wb = 541 new typename IEW::LdWritebackEvent(loadQueue[load_idx], 542 iewStage); 543 544 // We'll say this has a 1 cycle load-store forwarding latency 545 // for now. 546 // @todo: Need to make this a parameter. 547 wb->schedule(curTick); 548 549 // Should keep track of stat for forwarded data 550 return NoFault; 551 } else if ((store_has_lower_limit && lower_load_has_store_part) || 552 (store_has_upper_limit && upper_load_has_store_part) || 553 (lower_load_has_store_part && upper_load_has_store_part)) { 554 // This is the partial store-load forwarding case where a store 555 // has only part of the load's data. 556 557 // If it's already been written back, then don't worry about 558 // stalling on it. 559 if (storeQueue[store_idx].completed) { 560 continue; 561 } 562 563 // Must stall load and force it to retry, so long as it's the oldest 564 // load that needs to do so. 565 if (!stalled || 566 (stalled && 567 loadQueue[load_idx]->seqNum < 568 loadQueue[stallingLoadIdx]->seqNum)) { 569 stalled = true; 570 stallingStoreIsn = storeQueue[store_idx].inst->seqNum; 571 stallingLoadIdx = load_idx; 572 } 573 574 // Tell IQ/mem dep unit that this instruction will need to be 575 // rescheduled eventually 576 iewStage->rescheduleMemInst(loadQueue[load_idx]); 577 578 // Do not generate a writeback event as this instruction is not 579 // complete. 580 581 DPRINTF(LSQUnit, "Load-store forwarding mis-match. " 582 "Store idx %i to load addr %#x\n", 583 store_idx, req->vaddr); 584 585 return NoFault; 586 } 587 } 588 589 590 // If there's no forwarding case, then go access memory 591 DynInstPtr inst = loadQueue[load_idx]; 592 593 DPRINTF(LSQUnit, "Doing functional access for inst PC %#x\n", 594 loadQueue[load_idx]->readPC()); 595 assert(!req->data); 596 req->cmd = Read; 597 req->completionEvent = NULL; 598 req->time = curTick; 599 req->data = new uint8_t[64]; 600 Fault fault = cpu->read(req, data); 601 memcpy(req->data, &data, sizeof(T)); 602 603 ++usedPorts; 604 605 // if we have a cache, do cache access too 606 if (fault == NoFault && dcacheInterface) { 607 if (dcacheInterface->isBlocked()) { 608 // There's an older load that's already going to squash. 609 if (isLoadBlocked && blockedLoadSeqNum < inst->seqNum) 610 return NoFault; 611 612 isLoadBlocked = true; 613 loadBlockedHandled = false; 614 blockedLoadSeqNum = inst->seqNum; 615 // No fault occurred, even though the interface is blocked. 616 return NoFault; 617 } 618 DPRINTF(LSQUnit, "Doing timing access for inst PC %#x\n", 619 loadQueue[load_idx]->readPC()); 620/* 621 Addr debug_addr = ULL(0xfffffc0000be81a8); 622 if (req->vaddr == debug_addr) { 623 debug_break(); 624 } 625*/ 626 assert(!req->completionEvent); 627 req->completionEvent = 628 new typename IEW::LdWritebackEvent(loadQueue[load_idx], iewStage); 629 MemAccessResult result = dcacheInterface->access(req); 630 631 assert(dcacheInterface->doEvents()); 632 633 // Ugly hack to get an event scheduled *only* if the access is 634 // a miss. We really should add first-class support for this 635 // at some point. 636 if (result != MA_HIT) { 637 DPRINTF(LSQUnit, "LSQUnit: D-cache miss!\n"); 638 DPRINTF(Activity, "Activity: ld accessing mem miss [sn:%lli]\n", 639 inst->seqNum); 640 641 lastDcacheStall = curTick; 642 643// _status = DcacheMissStall; 644 645 } else { 646 DPRINTF(Activity, "Activity: ld accessing mem hit [sn:%lli]\n", 647 inst->seqNum); 648 649 DPRINTF(LSQUnit, "LSQUnit: D-cache hit!\n"); 650 } 651 } 652#if 0 653 // if we have a cache, do cache access too 654 if (dcacheInterface) { 655 if (dcacheInterface->isBlocked()) { 656 isLoadBlocked = true; 657 // No fault occurred, even though the interface is blocked. 658 return NoFault; 659 } 660 661 DPRINTF(LSQUnit, "LSQUnit: D-cache: PC:%#x reading from paddr:%#x " 662 "vaddr:%#x flags:%i\n", 663 inst->readPC(), req->paddr, req->vaddr, req->flags); 664 665 // Setup MemReq pointer 666 req->cmd = Read; 667 req->completionEvent = NULL; 668 req->time = curTick; 669 assert(!req->data); 670 req->data = new uint8_t[64]; 671 672 assert(!req->completionEvent); 673 req->completionEvent = 674 new typename IEW::LdWritebackEvent(loadQueue[load_idx], iewStage); 675 676 // Do Cache Access 677 MemAccessResult result = dcacheInterface->access(req); 678 679 // Ugly hack to get an event scheduled *only* if the access is 680 // a miss. We really should add first-class support for this 681 // at some point. 682 // @todo: Probably should support having no events 683 if (result != MA_HIT) { 684 DPRINTF(LSQUnit, "LSQUnit: D-cache miss!\n"); 685 DPRINTF(Activity, "Activity: ld accessing mem miss [sn:%lli]\n", 686 inst->seqNum); 687 688 lastDcacheStall = curTick; 689 690 _status = DcacheMissStall; 691 692 } else { 693 DPRINTF(Activity, "Activity: ld accessing mem hit [sn:%lli]\n", 694 inst->seqNum); 695 696 DPRINTF(LSQUnit, "LSQUnit: D-cache hit!\n"); 697 } 698 } else { 699 fatal("Must use D-cache with new memory system"); 700 } 701#endif 702 703 return fault; 704} 705 706template <class Impl> 707template <class T> 708Fault 709LSQUnit<Impl>::write(MemReqPtr &req, T &data, int store_idx) 710{ 711 assert(storeQueue[store_idx].inst); 712 713 DPRINTF(LSQUnit, "Doing write to store idx %i, addr %#x data %#x" 714 " | storeHead:%i [sn:%i]\n", 715 store_idx, req->paddr, data, storeHead, 716 storeQueue[store_idx].inst->seqNum); 717/* 718 if (req->flags & LOCKED) { 719 if (req->flags & UNCACHEABLE) { 720 req->result = 2; 721 } else { 722 req->result = 1; 723 } 724 } 725*/ 726 storeQueue[store_idx].req = req; 727 storeQueue[store_idx].size = sizeof(T); 728 storeQueue[store_idx].data = data; 729/* 730 Addr debug_addr = ULL(0xfffffc0000be81a8); 731 if (req->vaddr == debug_addr) { 732 debug_break(); 733 } 734*/ 735 // This function only writes the data to the store queue, so no fault 736 // can happen here. 737 return NoFault; 738} 739 740#endif // __CPU_O3_LSQ_UNIT_HH__ 741