lsq_unit.hh revision 5606
1/* 2 * Copyright (c) 2004-2006 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#ifndef __CPU_O3_LSQ_UNIT_HH__ 33#define __CPU_O3_LSQ_UNIT_HH__ 34 35#include <algorithm> 36#include <cstring> 37#include <map> 38#include <queue> 39 40#include "arch/faults.hh" 41#include "arch/locked_mem.hh" 42#include "config/full_system.hh" 43#include "base/fast_alloc.hh" 44#include "base/hashmap.hh" 45#include "cpu/inst_seq.hh" 46#include "mem/packet.hh" 47#include "mem/port.hh" 48 49class DerivO3CPUParams; 50 51/** 52 * Class that implements the actual LQ and SQ for each specific 53 * thread. Both are circular queues; load entries are freed upon 54 * committing, while store entries are freed once they writeback. The 55 * LSQUnit tracks if there are memory ordering violations, and also 56 * detects partial load to store forwarding cases (a store only has 57 * part of a load's data) that requires the load to wait until the 58 * store writes back. In the former case it holds onto the instruction 59 * until the dependence unit looks at it, and in the latter it stalls 60 * the LSQ until the store writes back. At that point the load is 61 * replayed. 62 */ 63template <class Impl> 64class LSQUnit { 65 protected: 66 typedef TheISA::IntReg IntReg; 67 public: 68 typedef typename Impl::O3CPU O3CPU; 69 typedef typename Impl::DynInstPtr DynInstPtr; 70 typedef typename Impl::CPUPol::IEW IEW; 71 typedef typename Impl::CPUPol::LSQ LSQ; 72 typedef typename Impl::CPUPol::IssueStruct IssueStruct; 73 74 public: 75 /** Constructs an LSQ unit. init() must be called prior to use. */ 76 LSQUnit(); 77 78 /** Initializes the LSQ unit with the specified number of entries. */ 79 void init(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params, 80 LSQ *lsq_ptr, unsigned maxLQEntries, unsigned maxSQEntries, 81 unsigned id); 82 83 /** Returns the name of the LSQ unit. */ 84 std::string name() const; 85 86 /** Registers statistics. */ 87 void regStats(); 88 89 /** Sets the pointer to the dcache port. */ 90 void setDcachePort(Port *dcache_port); 91 92 /** Switches out LSQ unit. */ 93 void switchOut(); 94 95 /** Takes over from another CPU's thread. */ 96 void takeOverFrom(); 97 98 /** Returns if the LSQ is switched out. */ 99 bool isSwitchedOut() { return switchedOut; } 100 101 /** Ticks the LSQ unit, which in this case only resets the number of 102 * used cache ports. 103 * @todo: Move the number of used ports up to the LSQ level so it can 104 * be shared by all LSQ units. 105 */ 106 void tick() { usedPorts = 0; } 107 108 /** Inserts an instruction. */ 109 void insert(DynInstPtr &inst); 110 /** Inserts a load instruction. */ 111 void insertLoad(DynInstPtr &load_inst); 112 /** Inserts a store instruction. */ 113 void insertStore(DynInstPtr &store_inst); 114 115 /** Executes a load instruction. */ 116 Fault executeLoad(DynInstPtr &inst); 117 118 Fault executeLoad(int lq_idx) { panic("Not implemented"); return NoFault; } 119 /** Executes a store instruction. */ 120 Fault executeStore(DynInstPtr &inst); 121 122 /** Commits the head load. */ 123 void commitLoad(); 124 /** Commits loads older than a specific sequence number. */ 125 void commitLoads(InstSeqNum &youngest_inst); 126 127 /** Commits stores older than a specific sequence number. */ 128 void commitStores(InstSeqNum &youngest_inst); 129 130 /** Writes back stores. */ 131 void writebackStores(); 132 133 /** Completes the data access that has been returned from the 134 * memory system. */ 135 void completeDataAccess(PacketPtr pkt); 136 137 /** Clears all the entries in the LQ. */ 138 void clearLQ(); 139 140 /** Clears all the entries in the SQ. */ 141 void clearSQ(); 142 143 /** Resizes the LQ to a given size. */ 144 void resizeLQ(unsigned size); 145 146 /** Resizes the SQ to a given size. */ 147 void resizeSQ(unsigned size); 148 149 /** Squashes all instructions younger than a specific sequence number. */ 150 void squash(const InstSeqNum &squashed_num); 151 152 /** Returns if there is a memory ordering violation. Value is reset upon 153 * call to getMemDepViolator(). 154 */ 155 bool violation() { return memDepViolator; } 156 157 /** Returns the memory ordering violator. */ 158 DynInstPtr getMemDepViolator(); 159 160 /** Returns if a load became blocked due to the memory system. */ 161 bool loadBlocked() 162 { return isLoadBlocked; } 163 164 /** Clears the signal that a load became blocked. */ 165 void clearLoadBlocked() 166 { isLoadBlocked = false; } 167 168 /** Returns if the blocked load was handled. */ 169 bool isLoadBlockedHandled() 170 { return loadBlockedHandled; } 171 172 /** Records the blocked load as being handled. */ 173 void setLoadBlockedHandled() 174 { loadBlockedHandled = true; } 175 176 /** Returns the number of free entries (min of free LQ and SQ entries). */ 177 unsigned numFreeEntries(); 178 179 /** Returns the number of loads ready to execute. */ 180 int numLoadsReady(); 181 182 /** Returns the number of loads in the LQ. */ 183 int numLoads() { return loads; } 184 185 /** Returns the number of stores in the SQ. */ 186 int numStores() { return stores; } 187 188 /** Returns if either the LQ or SQ is full. */ 189 bool isFull() { return lqFull() || sqFull(); } 190 191 /** Returns if the LQ is full. */ 192 bool lqFull() { return loads >= (LQEntries - 1); } 193 194 /** Returns if the SQ is full. */ 195 bool sqFull() { return stores >= (SQEntries - 1); } 196 197 /** Returns the number of instructions in the LSQ. */ 198 unsigned getCount() { return loads + stores; } 199 200 /** Returns if there are any stores to writeback. */ 201 bool hasStoresToWB() { return storesToWB; } 202 203 /** Returns the number of stores to writeback. */ 204 int numStoresToWB() { return storesToWB; } 205 206 /** Returns if the LSQ unit will writeback on this cycle. */ 207 bool willWB() { return storeQueue[storeWBIdx].canWB && 208 !storeQueue[storeWBIdx].completed && 209 !isStoreBlocked; } 210 211 /** Handles doing the retry. */ 212 void recvRetry(); 213 214 private: 215 /** Writes back the instruction, sending it to IEW. */ 216 void writeback(DynInstPtr &inst, PacketPtr pkt); 217 218 /** Handles completing the send of a store to memory. */ 219 void storePostSend(PacketPtr pkt); 220 221 /** Completes the store at the specified index. */ 222 void completeStore(int store_idx); 223 224 /** Increments the given store index (circular queue). */ 225 inline void incrStIdx(int &store_idx); 226 /** Decrements the given store index (circular queue). */ 227 inline void decrStIdx(int &store_idx); 228 /** Increments the given load index (circular queue). */ 229 inline void incrLdIdx(int &load_idx); 230 /** Decrements the given load index (circular queue). */ 231 inline void decrLdIdx(int &load_idx); 232 233 public: 234 /** Debugging function to dump instructions in the LSQ. */ 235 void dumpInsts(); 236 237 private: 238 /** Pointer to the CPU. */ 239 O3CPU *cpu; 240 241 /** Pointer to the IEW stage. */ 242 IEW *iewStage; 243 244 /** Pointer to the LSQ. */ 245 LSQ *lsq; 246 247 /** Pointer to the dcache port. Used only for sending. */ 248 Port *dcachePort; 249 250 /** Derived class to hold any sender state the LSQ needs. */ 251 class LSQSenderState : public Packet::SenderState, public FastAlloc 252 { 253 public: 254 /** Default constructor. */ 255 LSQSenderState() 256 : noWB(false) 257 { } 258 259 /** Instruction who initiated the access to memory. */ 260 DynInstPtr inst; 261 /** Whether or not it is a load. */ 262 bool isLoad; 263 /** The LQ/SQ index of the instruction. */ 264 int idx; 265 /** Whether or not the instruction will need to writeback. */ 266 bool noWB; 267 }; 268 269 /** Writeback event, specifically for when stores forward data to loads. */ 270 class WritebackEvent : public Event { 271 public: 272 /** Constructs a writeback event. */ 273 WritebackEvent(DynInstPtr &_inst, PacketPtr pkt, LSQUnit *lsq_ptr); 274 275 /** Processes the writeback event. */ 276 void process(); 277 278 /** Returns the description of this event. */ 279 const char *description() const; 280 281 private: 282 /** Instruction whose results are being written back. */ 283 DynInstPtr inst; 284 285 /** The packet that would have been sent to memory. */ 286 PacketPtr pkt; 287 288 /** The pointer to the LSQ unit that issued the store. */ 289 LSQUnit<Impl> *lsqPtr; 290 }; 291 292 public: 293 struct SQEntry { 294 /** Constructs an empty store queue entry. */ 295 SQEntry() 296 : inst(NULL), req(NULL), size(0), 297 canWB(0), committed(0), completed(0) 298 { 299 std::memset(data, 0, sizeof(data)); 300 } 301 302 /** Constructs a store queue entry for a given instruction. */ 303 SQEntry(DynInstPtr &_inst) 304 : inst(_inst), req(NULL), size(0), 305 canWB(0), committed(0), completed(0) 306 { 307 std::memset(data, 0, sizeof(data)); 308 } 309 310 /** The store instruction. */ 311 DynInstPtr inst; 312 /** The request for the store. */ 313 RequestPtr req; 314 /** The size of the store. */ 315 int size; 316 /** The store data. */ 317 char data[sizeof(IntReg)]; 318 /** Whether or not the store can writeback. */ 319 bool canWB; 320 /** Whether or not the store is committed. */ 321 bool committed; 322 /** Whether or not the store is completed. */ 323 bool completed; 324 }; 325 326 private: 327 /** The LSQUnit thread id. */ 328 unsigned lsqID; 329 330 /** The store queue. */ 331 std::vector<SQEntry> storeQueue; 332 333 /** The load queue. */ 334 std::vector<DynInstPtr> loadQueue; 335 336 /** The number of LQ entries, plus a sentinel entry (circular queue). 337 * @todo: Consider having var that records the true number of LQ entries. 338 */ 339 unsigned LQEntries; 340 /** The number of SQ entries, plus a sentinel entry (circular queue). 341 * @todo: Consider having var that records the true number of SQ entries. 342 */ 343 unsigned SQEntries; 344 345 /** The number of load instructions in the LQ. */ 346 int loads; 347 /** The number of store instructions in the SQ. */ 348 int stores; 349 /** The number of store instructions in the SQ waiting to writeback. */ 350 int storesToWB; 351 352 /** The index of the head instruction in the LQ. */ 353 int loadHead; 354 /** The index of the tail instruction in the LQ. */ 355 int loadTail; 356 357 /** The index of the head instruction in the SQ. */ 358 int storeHead; 359 /** The index of the first instruction that may be ready to be 360 * written back, and has not yet been written back. 361 */ 362 int storeWBIdx; 363 /** The index of the tail instruction in the SQ. */ 364 int storeTail; 365 366 /// @todo Consider moving to a more advanced model with write vs read ports 367 /** The number of cache ports available each cycle. */ 368 int cachePorts; 369 370 /** The number of used cache ports in this cycle. */ 371 int usedPorts; 372 373 /** Is the LSQ switched out. */ 374 bool switchedOut; 375 376 //list<InstSeqNum> mshrSeqNums; 377 378 /** Wire to read information from the issue stage time queue. */ 379 typename TimeBuffer<IssueStruct>::wire fromIssue; 380 381 /** Whether or not the LSQ is stalled. */ 382 bool stalled; 383 /** The store that causes the stall due to partial store to load 384 * forwarding. 385 */ 386 InstSeqNum stallingStoreIsn; 387 /** The index of the above store. */ 388 int stallingLoadIdx; 389 390 /** The packet that needs to be retried. */ 391 PacketPtr retryPkt; 392 393 /** Whehter or not a store is blocked due to the memory system. */ 394 bool isStoreBlocked; 395 396 /** Whether or not a load is blocked due to the memory system. */ 397 bool isLoadBlocked; 398 399 /** Has the blocked load been handled. */ 400 bool loadBlockedHandled; 401 402 /** The sequence number of the blocked load. */ 403 InstSeqNum blockedLoadSeqNum; 404 405 /** The oldest load that caused a memory ordering violation. */ 406 DynInstPtr memDepViolator; 407 408 // Will also need how many read/write ports the Dcache has. Or keep track 409 // of that in stage that is one level up, and only call executeLoad/Store 410 // the appropriate number of times. 411 /** Total number of loads forwaded from LSQ stores. */ 412 Stats::Scalar<> lsqForwLoads; 413 414 /** Total number of loads ignored due to invalid addresses. */ 415 Stats::Scalar<> invAddrLoads; 416 417 /** Total number of squashed loads. */ 418 Stats::Scalar<> lsqSquashedLoads; 419 420 /** Total number of responses from the memory system that are 421 * ignored due to the instruction already being squashed. */ 422 Stats::Scalar<> lsqIgnoredResponses; 423 424 /** Tota number of memory ordering violations. */ 425 Stats::Scalar<> lsqMemOrderViolation; 426 427 /** Total number of squashed stores. */ 428 Stats::Scalar<> lsqSquashedStores; 429 430 /** Total number of software prefetches ignored due to invalid addresses. */ 431 Stats::Scalar<> invAddrSwpfs; 432 433 /** Ready loads blocked due to partial store-forwarding. */ 434 Stats::Scalar<> lsqBlockedLoads; 435 436 /** Number of loads that were rescheduled. */ 437 Stats::Scalar<> lsqRescheduledLoads; 438 439 /** Number of times the LSQ is blocked due to the cache. */ 440 Stats::Scalar<> lsqCacheBlocked; 441 442 public: 443 /** Executes the load at the given index. */ 444 template <class T> 445 Fault read(Request *req, T &data, int load_idx); 446 447 /** Executes the store at the given index. */ 448 template <class T> 449 Fault write(Request *req, T &data, int store_idx); 450 451 /** Returns the index of the head load instruction. */ 452 int getLoadHead() { return loadHead; } 453 /** Returns the sequence number of the head load instruction. */ 454 InstSeqNum getLoadHeadSeqNum() 455 { 456 if (loadQueue[loadHead]) { 457 return loadQueue[loadHead]->seqNum; 458 } else { 459 return 0; 460 } 461 462 } 463 464 /** Returns the index of the head store instruction. */ 465 int getStoreHead() { return storeHead; } 466 /** Returns the sequence number of the head store instruction. */ 467 InstSeqNum getStoreHeadSeqNum() 468 { 469 if (storeQueue[storeHead].inst) { 470 return storeQueue[storeHead].inst->seqNum; 471 } else { 472 return 0; 473 } 474 475 } 476 477 /** Returns whether or not the LSQ unit is stalled. */ 478 bool isStalled() { return stalled; } 479}; 480 481template <class Impl> 482template <class T> 483Fault 484LSQUnit<Impl>::read(Request *req, T &data, int load_idx) 485{ 486 DynInstPtr load_inst = loadQueue[load_idx]; 487 488 assert(load_inst); 489 490 assert(!load_inst->isExecuted()); 491 492 // Make sure this isn't an uncacheable access 493 // A bit of a hackish way to get uncached accesses to work only if they're 494 // at the head of the LSQ and are ready to commit (at the head of the ROB 495 // too). 496 if (req->isUncacheable() && 497 (load_idx != loadHead || !load_inst->isAtCommit())) { 498 iewStage->rescheduleMemInst(load_inst); 499 ++lsqRescheduledLoads; 500 501 // Must delete request now that it wasn't handed off to 502 // memory. This is quite ugly. @todo: Figure out the proper 503 // place to really handle request deletes. 504 delete req; 505 return TheISA::genMachineCheckFault(); 506 } 507 508 // Check the SQ for any previous stores that might lead to forwarding 509 int store_idx = load_inst->sqIdx; 510 511 int store_size = 0; 512 513 DPRINTF(LSQUnit, "Read called, load idx: %i, store idx: %i, " 514 "storeHead: %i addr: %#x\n", 515 load_idx, store_idx, storeHead, req->getPaddr()); 516 517 if (req->isLocked()) { 518 // Disable recording the result temporarily. Writing to misc 519 // regs normally updates the result, but this is not the 520 // desired behavior when handling store conditionals. 521 load_inst->recordResult = false; 522 TheISA::handleLockedRead(load_inst.get(), req); 523 load_inst->recordResult = true; 524 } 525 526 while (store_idx != -1) { 527 // End once we've reached the top of the LSQ 528 if (store_idx == storeWBIdx) { 529 break; 530 } 531 532 // Move the index to one younger 533 if (--store_idx < 0) 534 store_idx += SQEntries; 535 536 assert(storeQueue[store_idx].inst); 537 538 store_size = storeQueue[store_idx].size; 539 540 if (store_size == 0) 541 continue; 542 else if (storeQueue[store_idx].inst->uncacheable()) 543 continue; 544 545 assert(storeQueue[store_idx].inst->effAddrValid); 546 547 // Check if the store data is within the lower and upper bounds of 548 // addresses that the request needs. 549 bool store_has_lower_limit = 550 req->getVaddr() >= storeQueue[store_idx].inst->effAddr; 551 bool store_has_upper_limit = 552 (req->getVaddr() + req->getSize()) <= 553 (storeQueue[store_idx].inst->effAddr + store_size); 554 bool lower_load_has_store_part = 555 req->getVaddr() < (storeQueue[store_idx].inst->effAddr + 556 store_size); 557 bool upper_load_has_store_part = 558 (req->getVaddr() + req->getSize()) > 559 storeQueue[store_idx].inst->effAddr; 560 561 // If the store's data has all of the data needed, we can forward. 562 if ((store_has_lower_limit && store_has_upper_limit)) { 563 // Get shift amount for offset into the store's data. 564 int shift_amt = req->getVaddr() & (store_size - 1); 565 566 memcpy(&data, storeQueue[store_idx].data + shift_amt, sizeof(T)); 567 568 assert(!load_inst->memData); 569 load_inst->memData = new uint8_t[64]; 570 571 memcpy(load_inst->memData, 572 storeQueue[store_idx].data + shift_amt, req->getSize()); 573 574 DPRINTF(LSQUnit, "Forwarding from store idx %i to load to " 575 "addr %#x, data %#x\n", 576 store_idx, req->getVaddr(), data); 577 578 PacketPtr data_pkt = new Packet(req, MemCmd::ReadReq, 579 Packet::Broadcast); 580 data_pkt->dataStatic(load_inst->memData); 581 582 WritebackEvent *wb = new WritebackEvent(load_inst, data_pkt, this); 583 584 // We'll say this has a 1 cycle load-store forwarding latency 585 // for now. 586 // @todo: Need to make this a parameter. 587 cpu->schedule(wb, curTick); 588 589 ++lsqForwLoads; 590 return NoFault; 591 } else if ((store_has_lower_limit && lower_load_has_store_part) || 592 (store_has_upper_limit && upper_load_has_store_part) || 593 (lower_load_has_store_part && upper_load_has_store_part)) { 594 // This is the partial store-load forwarding case where a store 595 // has only part of the load's data. 596 597 // If it's already been written back, then don't worry about 598 // stalling on it. 599 if (storeQueue[store_idx].completed) { 600 panic("Should not check one of these"); 601 continue; 602 } 603 604 // Must stall load and force it to retry, so long as it's the oldest 605 // load that needs to do so. 606 if (!stalled || 607 (stalled && 608 load_inst->seqNum < 609 loadQueue[stallingLoadIdx]->seqNum)) { 610 stalled = true; 611 stallingStoreIsn = storeQueue[store_idx].inst->seqNum; 612 stallingLoadIdx = load_idx; 613 } 614 615 // Tell IQ/mem dep unit that this instruction will need to be 616 // rescheduled eventually 617 iewStage->rescheduleMemInst(load_inst); 618 iewStage->decrWb(load_inst->seqNum); 619 load_inst->clearIssued(); 620 ++lsqRescheduledLoads; 621 622 // Do not generate a writeback event as this instruction is not 623 // complete. 624 DPRINTF(LSQUnit, "Load-store forwarding mis-match. " 625 "Store idx %i to load addr %#x\n", 626 store_idx, req->getVaddr()); 627 628 // Must delete request now that it wasn't handed off to 629 // memory. This is quite ugly. @todo: Figure out the 630 // proper place to really handle request deletes. 631 delete req; 632 633 return NoFault; 634 } 635 } 636 637 // If there's no forwarding case, then go access memory 638 DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %#x\n", 639 load_inst->seqNum, load_inst->readPC()); 640 641 assert(!load_inst->memData); 642 load_inst->memData = new uint8_t[64]; 643 644 ++usedPorts; 645 646 // if we the cache is not blocked, do cache access 647 if (!lsq->cacheBlocked()) { 648 PacketPtr data_pkt = 649 new Packet(req, 650 (req->isLocked() ? 651 MemCmd::LoadLockedReq : MemCmd::ReadReq), 652 Packet::Broadcast); 653 data_pkt->dataStatic(load_inst->memData); 654 655 LSQSenderState *state = new LSQSenderState; 656 state->isLoad = true; 657 state->idx = load_idx; 658 state->inst = load_inst; 659 data_pkt->senderState = state; 660 661 if (!dcachePort->sendTiming(data_pkt)) { 662 // Delete state and data packet because a load retry 663 // initiates a pipeline restart; it does not retry. 664 delete state; 665 delete data_pkt->req; 666 delete data_pkt; 667 668 req = NULL; 669 670 // If the access didn't succeed, tell the LSQ by setting 671 // the retry thread id. 672 lsq->setRetryTid(lsqID); 673 } 674 } 675 676 // If the cache was blocked, or has become blocked due to the access, 677 // handle it. 678 if (lsq->cacheBlocked()) { 679 if (req) 680 delete req; 681 682 ++lsqCacheBlocked; 683 684 iewStage->decrWb(load_inst->seqNum); 685 // There's an older load that's already going to squash. 686 if (isLoadBlocked && blockedLoadSeqNum < load_inst->seqNum) 687 return NoFault; 688 689 // Record that the load was blocked due to memory. This 690 // load will squash all instructions after it, be 691 // refetched, and re-executed. 692 isLoadBlocked = true; 693 loadBlockedHandled = false; 694 blockedLoadSeqNum = load_inst->seqNum; 695 // No fault occurred, even though the interface is blocked. 696 return NoFault; 697 } 698 699 return NoFault; 700} 701 702template <class Impl> 703template <class T> 704Fault 705LSQUnit<Impl>::write(Request *req, T &data, int store_idx) 706{ 707 assert(storeQueue[store_idx].inst); 708 709 DPRINTF(LSQUnit, "Doing write to store idx %i, addr %#x data %#x" 710 " | storeHead:%i [sn:%i]\n", 711 store_idx, req->getPaddr(), data, storeHead, 712 storeQueue[store_idx].inst->seqNum); 713 714 storeQueue[store_idx].req = req; 715 storeQueue[store_idx].size = sizeof(T); 716 assert(sizeof(T) <= sizeof(storeQueue[store_idx].data)); 717 718 T gData = htog(data); 719 memcpy(storeQueue[store_idx].data, &gData, sizeof(T)); 720 721 // This function only writes the data to the store queue, so no fault 722 // can happen here. 723 return NoFault; 724} 725 726#endif // __CPU_O3_LSQ_UNIT_HH__ 727