lsq.hh revision 13590:d7e018859709
1/* 2 * Copyright (c) 2011-2012, 2014, 2018 ARM Limited 3 * Copyright (c) 2013 Advanced Micro Devices, Inc. 4 * All rights reserved 5 * 6 * The license below extends only to copyright in the software and shall 7 * not be construed as granting a license to any other intellectual 8 * property including but not limited to intellectual property relating 9 * to a hardware implementation of the functionality of the software 10 * licensed hereunder. You may use the software subject to the license 11 * terms below provided that you ensure that this notice is replicated 12 * unmodified and in its entirety in all distributions of the software, 13 * modified or unmodified, in source code or in binary form. 14 * 15 * Copyright (c) 2004-2006 The Regents of The University of Michigan 16 * All rights reserved. 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions are 20 * met: redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer; 22 * redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution; 25 * neither the name of the copyright holders nor the names of its 26 * contributors may be used to endorse or promote products derived from 27 * this software without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Authors: Korey Sewell 42 */ 43 44#ifndef __CPU_O3_LSQ_HH__ 45#define __CPU_O3_LSQ_HH__ 46 47#include <map> 48#include <queue> 49 50#include "arch/generic/tlb.hh" 51#include "cpu/inst_seq.hh" 52#include "cpu/o3/lsq_unit.hh" 53#include "enums/SMTQueuePolicy.hh" 54#include "mem/port.hh" 55#include "sim/sim_object.hh" 56 57struct DerivO3CPUParams; 58 59template <class Impl> 60class LSQ 61 62{ 63 public: 64 typedef typename Impl::O3CPU O3CPU; 65 typedef typename Impl::DynInstPtr DynInstPtr; 66 typedef typename Impl::CPUPol::IEW IEW; 67 typedef typename Impl::CPUPol::LSQUnit LSQUnit; 68 69 class LSQRequest; 70 /** Derived class to hold any sender state the LSQ needs. */ 71 class LSQSenderState : public Packet::SenderState 72 { 73 protected: 74 /** The senderState needs to know the LSQRequest who owns it. */ 75 LSQRequest* _request; 76 77 /** Default constructor. */ 78 LSQSenderState(LSQRequest* request, bool isLoad_) 79 : _request(request), mainPkt(nullptr), pendingPacket(nullptr), 80 outstanding(0), isLoad(isLoad_), needWB(isLoad_), isSplit(false), 81 pktToSend(false), deleted(false) 82 { } 83 public: 84 85 /** Instruction which initiated the access to memory. */ 86 DynInstPtr inst; 87 /** The main packet from a split load, used during writeback. */ 88 PacketPtr mainPkt; 89 /** A second packet from a split store that needs sending. */ 90 PacketPtr pendingPacket; 91 /** Number of outstanding packets to complete. */ 92 uint8_t outstanding; 93 /** Whether or not it is a load. */ 94 bool isLoad; 95 /** Whether or not the instruction will need to writeback. */ 96 bool needWB; 97 /** Whether or not this access is split in two. */ 98 bool isSplit; 99 /** Whether or not there is a packet that needs sending. */ 100 bool pktToSend; 101 /** Has the request been deleted? 102 * LSQ entries can be squashed before the response comes back. in that 103 * case the SenderState knows. 104 */ 105 bool deleted; 106 ContextID contextId() { return inst->contextId(); } 107 108 /** Completes a packet and returns whether the access is finished. */ 109 inline bool isComplete() { return outstanding == 0; } 110 inline void deleteRequest() { deleted = true; } 111 inline bool alive() { return !deleted; } 112 LSQRequest* request() { return _request; } 113 virtual void complete() = 0; 114 void writebackDone() { _request->writebackDone(); } 115 }; 116 117 /** Memory operation metadata. 118 * This class holds the information about a memory operation. It lives 119 * from initiateAcc to resource deallocation at commit or squash. 120 * LSQRequest objects are owned by the LQ/SQ Entry in the LSQUnit that 121 * holds the operation. It is also used by the LSQSenderState. In addition, 122 * the LSQRequest is a TranslationState, therefore, upon squash, there must 123 * be a defined ownership transferal in case the LSQ resources are 124 * deallocated before the TLB is done using the TranslationState. If that 125 * happens, the LSQRequest will be self-owned, and responsible to detect 126 * that its services are no longer required and self-destruct. 127 * 128 * Lifetime of a LSQRequest: 129 * +--------------------+ 130 * |LSQ creates and owns| 131 * +--------------------+ 132 * | 133 * +--------------------+ 134 * | Initate translation| 135 * +--------------------+ 136 * | 137 * ___^___ 138 * ___/ \___ 139 * ______/ Squashed? \ 140 * | \___ ___/ 141 * | \___ ___/ 142 * | v 143 * | | 144 * | +--------------------+ 145 * | | Translation done | 146 * | +--------------------+ 147 * | | 148 * | +--------------------+ 149 * | | Send packet |<------+ 150 * | +--------------------+ | 151 * | | | 152 * | ___^___ | 153 * | ___/ \___ | 154 * | ____/ Squashed? \ | 155 * | | \___ ___/ | 156 * | | \___ ___/ | 157 * | | v | 158 * | | | | 159 * | | ___^___ | 160 * | | ___/ \___ | 161 * | | / Done? \__________| 162 * | | \___ ___/ 163 * | | \___ ___/ 164 * | | v 165 * | | | 166 * | | +--------------------+ 167 * | | | Manage stuff | 168 * | | | Free resources | 169 * | | +--------------------+ 170 * | | 171 * | | +--------------------+ 172 * | | | senderState owns | 173 * | +->| onRecvTimingResp | 174 * | | free resources | 175 * | +--------------------+ 176 * | 177 * | +----------------------+ 178 * | | self owned (Trans) | 179 * +-->| on TranslationFinish | 180 * | free resources | 181 * +----------------------+ 182 * 183 * 184 */ 185 class LSQRequest : public BaseTLB::Translation 186 { 187 protected: 188 typedef uint32_t FlagsStorage; 189 typedef ::Flags<FlagsStorage> FlagsType; 190 191 enum Flag : FlagsStorage 192 { 193 IsLoad = 0x00000001, 194 /** True if this is a store that writes registers (SC). */ 195 WbStore = 0x00000002, 196 Delayed = 0x00000004, 197 IsSplit = 0x00000008, 198 /** True if any translation has been sent to TLB. */ 199 TranslationStarted = 0x00000010, 200 /** True if there are un-replied outbound translations.. */ 201 TranslationFinished = 0x00000020, 202 Sent = 0x00000040, 203 Retry = 0x00000080, 204 Complete = 0x00000100, 205 /** Ownership tracking flags. */ 206 /** Translation squashed. */ 207 TranslationSquashed = 0x00000200, 208 /** Request discarded */ 209 Discarded = 0x00000400, 210 /** LSQ resources freed. */ 211 LSQEntryFreed = 0x00000800, 212 /** Store written back. */ 213 WritebackScheduled = 0x00001000, 214 WritebackDone = 0x00002000 215 }; 216 FlagsType flags; 217 218 enum class State 219 { 220 NotIssued, 221 Translation, 222 Request, 223 Complete, 224 Squashed, 225 Fault, 226 }; 227 State _state; 228 LSQSenderState* _senderState; 229 void setState(const State& newState) { _state = newState; } 230 231 uint32_t numTranslatedFragments; 232 uint32_t numInTranslationFragments; 233 234 /** LQ/SQ entry idx. */ 235 uint32_t _entryIdx; 236 237 void markDelayed() { flags.set(Flag::Delayed); } 238 bool isDelayed() { return flags.isSet(Flag::Delayed); } 239 240 public: 241 LSQUnit& _port; 242 const DynInstPtr _inst; 243 uint32_t _taskId; 244 PacketDataPtr _data; 245 std::vector<PacketPtr> _packets; 246 std::vector<RequestPtr> _requests; 247 std::vector<Fault> _fault; 248 uint64_t* _res; 249 const Addr _addr; 250 const uint32_t _size; 251 const Request::Flags _flags; 252 uint32_t _numOutstandingPackets; 253 protected: 254 LSQUnit* lsqUnit() { return &_port; } 255 LSQRequest(LSQUnit* port, const DynInstPtr& inst, bool isLoad) : 256 _state(State::NotIssued), _senderState(nullptr), 257 _port(*port), _inst(inst), _data(nullptr), 258 _res(nullptr), _addr(0), _size(0), _flags(0), 259 _numOutstandingPackets(0) 260 { 261 flags.set(Flag::IsLoad, isLoad); 262 flags.set(Flag::WbStore, _inst->isStoreConditional()); 263 install(); 264 } 265 LSQRequest(LSQUnit* port, const DynInstPtr& inst, bool isLoad, 266 const Addr& addr, const uint32_t& size, 267 const Request::Flags& flags_, 268 PacketDataPtr data = nullptr, uint64_t* res = nullptr) 269 : _state(State::NotIssued), _senderState(nullptr), 270 numTranslatedFragments(0), 271 numInTranslationFragments(0), 272 _port(*port), _inst(inst), _data(data), 273 _res(res), _addr(addr), _size(size), 274 _flags(flags_), 275 _numOutstandingPackets(0) 276 { 277 flags.set(Flag::IsLoad, isLoad); 278 flags.set(Flag::WbStore, _inst->isStoreConditional()); 279 install(); 280 } 281 282 bool 283 isLoad() const 284 { 285 return flags.isSet(Flag::IsLoad); 286 } 287 288 /** Install the request in the LQ/SQ. */ 289 void install() 290 { 291 if (isLoad()) { 292 _port.loadQueue[_inst->lqIdx].setRequest(this); 293 } else { 294 _port.storeQueue[_inst->sqIdx].setRequest(this); 295 } 296 } 297 virtual bool 298 squashed() const override 299 { 300 return _inst->isSquashed(); 301 } 302 303 /** 304 * Test if the LSQRequest has been released, i.e. self-owned. 305 * An LSQRequest manages itself when the resources on the LSQ are freed 306 * but the translation is still going on and the LSQEntry was freed. 307 */ 308 bool 309 isReleased() 310 { 311 return flags.isSet(Flag::LSQEntryFreed) || 312 flags.isSet(Flag::Discarded); 313 } 314 315 /** Release the LSQRequest. 316 * Notify the sender state that the request it points to is not valid 317 * anymore. Understand if the request is orphan (self-managed) and if 318 * so, mark it as freed, else destroy it, as this means 319 * the end of its life cycle. 320 * An LSQRequest is orphan when its resources are released 321 * but there is any in-flight translation request to the TLB or access 322 * request to the memory. 323 */ 324 void release(Flag reason) 325 { 326 assert(reason == Flag::LSQEntryFreed || reason == Flag::Discarded); 327 if (!isAnyOutstandingRequest()) { 328 delete this; 329 } else { 330 if (_senderState) { 331 _senderState->deleteRequest(); 332 } 333 flags.set(reason); 334 } 335 } 336 337 /** Destructor. 338 * The LSQRequest owns the request. If the packet has already been 339 * sent, the sender state will be deleted upon receiving the reply. 340 */ 341 virtual ~LSQRequest() 342 { 343 assert(!isAnyOutstandingRequest()); 344 _inst->savedReq = nullptr; 345 if (_senderState) 346 delete _senderState; 347 348 for (auto r: _packets) 349 delete r; 350 }; 351 352 353 public: 354 /** Convenience getters/setters. */ 355 /** @{ */ 356 /** Set up Context numbers. */ 357 void 358 setContext(const ContextID& context_id) 359 { 360 request()->setContext(context_id); 361 } 362 363 const DynInstPtr& 364 instruction() 365 { 366 return _inst; 367 } 368 369 /** Set up virtual request. 370 * For a previously allocated Request objects. 371 */ 372 void 373 setVirt(int asid, Addr vaddr, unsigned size, Request::Flags flags_, 374 MasterID mid, Addr pc) 375 { 376 request()->setVirt(asid, vaddr, size, flags_, mid, pc); 377 } 378 379 void 380 taskId(const uint32_t& v) 381 { 382 _taskId = v; 383 for (auto& r: _requests) 384 r->taskId(v); 385 } 386 387 uint32_t taskId() const { return _taskId; } 388 RequestPtr request(int idx = 0) { return _requests.at(idx); } 389 390 const RequestPtr 391 request(int idx = 0) const 392 { 393 return _requests.at(idx); 394 } 395 396 Addr getVaddr(int idx = 0) const { return request(idx)->getVaddr(); } 397 virtual void initiateTranslation() = 0; 398 399 PacketPtr packet(int idx = 0) { return _packets.at(idx); } 400 401 virtual PacketPtr 402 mainPacket() 403 { 404 assert (_packets.size() == 1); 405 return packet(); 406 } 407 408 virtual RequestPtr 409 mainRequest() 410 { 411 assert (_requests.size() == 1); 412 return request(); 413 } 414 415 void 416 senderState(LSQSenderState* st) 417 { 418 _senderState = st; 419 for (auto& pkt: _packets) { 420 if (pkt) 421 pkt->senderState = st; 422 } 423 } 424 425 const LSQSenderState* 426 senderState() const 427 { 428 return _senderState; 429 } 430 431 /** 432 * Mark senderState as discarded. This will cause to discard response 433 * packets from the cache. 434 */ 435 void 436 discardSenderState() 437 { 438 assert(_senderState); 439 _senderState->deleteRequest(); 440 } 441 442 /** 443 * Test if there is any in-flight translation or mem access request 444 */ 445 bool 446 isAnyOutstandingRequest() 447 { 448 return numInTranslationFragments > 0 || 449 _numOutstandingPackets > 0 || 450 (flags.isSet(Flag::WritebackScheduled) && 451 !flags.isSet(Flag::WritebackDone)); 452 } 453 454 bool 455 isSplit() const 456 { 457 return flags.isSet(Flag::IsSplit); 458 } 459 /** @} */ 460 virtual bool recvTimingResp(PacketPtr pkt) = 0; 461 virtual void sendPacketToCache() = 0; 462 virtual void buildPackets() = 0; 463 464 /** 465 * Memory mapped IPR accesses 466 */ 467 virtual void handleIprWrite(ThreadContext *thread, PacketPtr pkt) = 0; 468 virtual Cycles handleIprRead(ThreadContext *thread, PacketPtr pkt) = 0; 469 470 /** 471 * Test if the request accesses a particular cache line. 472 */ 473 virtual bool isCacheBlockHit(Addr blockAddr, Addr cacheBlockMask) = 0; 474 475 /** Update the status to reflect that a packet was sent. */ 476 void 477 packetSent() 478 { 479 flags.set(Flag::Sent); 480 } 481 /** Update the status to reflect that a packet was not sent. 482 * When a packet fails to be sent, we mark the request as needing a 483 * retry. Note that Retry flag is sticky. 484 */ 485 void 486 packetNotSent() 487 { 488 flags.set(Flag::Retry); 489 flags.clear(Flag::Sent); 490 } 491 492 void sendFragmentToTranslation(int i); 493 bool 494 isComplete() 495 { 496 return flags.isSet(Flag::Complete); 497 } 498 499 bool 500 isInTranslation() 501 { 502 return _state == State::Translation; 503 } 504 505 bool 506 isTranslationComplete() 507 { 508 return flags.isSet(Flag::TranslationStarted) && 509 !isInTranslation(); 510 } 511 512 bool 513 isTranslationBlocked() 514 { 515 return _state == State::Translation && 516 flags.isSet(Flag::TranslationStarted) && 517 !flags.isSet(Flag::TranslationFinished); 518 } 519 520 bool 521 isSent() 522 { 523 return flags.isSet(Flag::Sent); 524 } 525 526 /** 527 * The LSQ entry is cleared 528 */ 529 void 530 freeLSQEntry() 531 { 532 release(Flag::LSQEntryFreed); 533 } 534 535 /** 536 * The request is discarded (e.g. partial store-load forwarding) 537 */ 538 void 539 discard() 540 { 541 release(Flag::Discarded); 542 } 543 544 void 545 packetReplied() 546 { 547 assert(_numOutstandingPackets > 0); 548 _numOutstandingPackets--; 549 if (_numOutstandingPackets == 0 && isReleased()) 550 delete this; 551 } 552 553 void 554 writebackScheduled() 555 { 556 assert(!flags.isSet(Flag::WritebackScheduled)); 557 flags.set(Flag::WritebackScheduled); 558 } 559 560 void 561 writebackDone() 562 { 563 flags.set(Flag::WritebackDone); 564 /* If the lsq resources are already free */ 565 if (isReleased()) { 566 delete this; 567 } 568 } 569 570 void 571 squashTranslation() 572 { 573 assert(numInTranslationFragments == 0); 574 flags.set(Flag::TranslationSquashed); 575 /* If we are on our own, self-destruct. */ 576 if (isReleased()) { 577 delete this; 578 } 579 } 580 581 void 582 complete() 583 { 584 flags.set(Flag::Complete); 585 } 586 }; 587 588 class SingleDataRequest : public LSQRequest 589 { 590 protected: 591 /* Given that we are inside templates, children need explicit 592 * declaration of the names in the parent class. */ 593 using Flag = typename LSQRequest::Flag; 594 using State = typename LSQRequest::State; 595 using LSQRequest::_fault; 596 using LSQRequest::_inst; 597 using LSQRequest::_packets; 598 using LSQRequest::_port; 599 using LSQRequest::_res; 600 using LSQRequest::_senderState; 601 using LSQRequest::_state; 602 using LSQRequest::flags; 603 using LSQRequest::isLoad; 604 using LSQRequest::isTranslationComplete; 605 using LSQRequest::lsqUnit; 606 using LSQRequest::request; 607 using LSQRequest::sendFragmentToTranslation; 608 using LSQRequest::setState; 609 using LSQRequest::numInTranslationFragments; 610 using LSQRequest::numTranslatedFragments; 611 using LSQRequest::_numOutstandingPackets; 612 public: 613 SingleDataRequest(LSQUnit* port, const DynInstPtr& inst, bool isLoad, 614 const Addr& addr, const uint32_t& size, 615 const Request::Flags& flags_, 616 PacketDataPtr data = nullptr, 617 uint64_t* res = nullptr) : 618 LSQRequest(port, inst, isLoad, addr, size, flags_, data, res) 619 { 620 LSQRequest::_requests.push_back( 621 std::make_shared<Request>(inst->getASID(), addr, size, flags_, 622 inst->masterId(), inst->instAddr(), inst->contextId())); 623 LSQRequest::_requests.back()->setReqInstSeqNum(inst->seqNum); 624 } 625 inline virtual ~SingleDataRequest() {} 626 virtual void initiateTranslation(); 627 virtual void finish(const Fault &fault, const RequestPtr &req, 628 ThreadContext* tc, BaseTLB::Mode mode); 629 virtual bool recvTimingResp(PacketPtr pkt); 630 virtual void sendPacketToCache(); 631 virtual void buildPackets(); 632 virtual void handleIprWrite(ThreadContext *thread, PacketPtr pkt); 633 virtual Cycles handleIprRead(ThreadContext *thread, PacketPtr pkt); 634 virtual bool isCacheBlockHit(Addr blockAddr, Addr cacheBlockMask); 635 }; 636 637 class SplitDataRequest : public LSQRequest 638 { 639 protected: 640 /* Given that we are inside templates, children need explicit 641 * declaration of the names in the parent class. */ 642 using Flag = typename LSQRequest::Flag; 643 using State = typename LSQRequest::State; 644 using LSQRequest::_addr; 645 using LSQRequest::_data; 646 using LSQRequest::_fault; 647 using LSQRequest::_flags; 648 using LSQRequest::_inst; 649 using LSQRequest::_packets; 650 using LSQRequest::_port; 651 using LSQRequest::_requests; 652 using LSQRequest::_res; 653 using LSQRequest::_senderState; 654 using LSQRequest::_size; 655 using LSQRequest::_state; 656 using LSQRequest::_taskId; 657 using LSQRequest::flags; 658 using LSQRequest::isLoad; 659 using LSQRequest::isTranslationComplete; 660 using LSQRequest::lsqUnit; 661 using LSQRequest::numInTranslationFragments; 662 using LSQRequest::numTranslatedFragments; 663 using LSQRequest::request; 664 using LSQRequest::sendFragmentToTranslation; 665 using LSQRequest::setState; 666 using LSQRequest::_numOutstandingPackets; 667 668 uint32_t numFragments; 669 uint32_t numReceivedPackets; 670 RequestPtr mainReq; 671 PacketPtr _mainPacket; 672 673 674 public: 675 SplitDataRequest(LSQUnit* port, const DynInstPtr& inst, bool isLoad, 676 const Addr& addr, const uint32_t& size, 677 const Request::Flags & flags_, 678 PacketDataPtr data = nullptr, 679 uint64_t* res = nullptr) : 680 LSQRequest(port, inst, isLoad, addr, size, flags_, data, res), 681 numFragments(0), 682 numReceivedPackets(0), 683 mainReq(nullptr), 684 _mainPacket(nullptr) 685 { 686 flags.set(Flag::IsSplit); 687 } 688 virtual ~SplitDataRequest() 689 { 690 if (mainReq) { 691 mainReq = nullptr; 692 } 693 if (_mainPacket) { 694 delete _mainPacket; 695 _mainPacket = nullptr; 696 } 697 } 698 virtual void finish(const Fault &fault, const RequestPtr &req, 699 ThreadContext* tc, BaseTLB::Mode mode); 700 virtual bool recvTimingResp(PacketPtr pkt); 701 virtual void initiateTranslation(); 702 virtual void sendPacketToCache(); 703 virtual void buildPackets(); 704 705 virtual void handleIprWrite(ThreadContext *thread, PacketPtr pkt); 706 virtual Cycles handleIprRead(ThreadContext *thread, PacketPtr pkt); 707 virtual bool isCacheBlockHit(Addr blockAddr, Addr cacheBlockMask); 708 709 virtual RequestPtr mainRequest(); 710 virtual PacketPtr mainPacket(); 711 }; 712 713 /** Constructs an LSQ with the given parameters. */ 714 LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params); 715 ~LSQ() { } 716 717 /** Returns the name of the LSQ. */ 718 std::string name() const; 719 720 /** Registers statistics of each LSQ unit. */ 721 void regStats(); 722 723 /** Sets the pointer to the list of active threads. */ 724 void setActiveThreads(std::list<ThreadID> *at_ptr); 725 726 /** Perform sanity checks after a drain. */ 727 void drainSanityCheck() const; 728 /** Has the LSQ drained? */ 729 bool isDrained() const; 730 /** Takes over execution from another CPU's thread. */ 731 void takeOverFrom(); 732 733 /** Number of entries needed for the given amount of threads.*/ 734 int entryAmount(ThreadID num_threads); 735 736 /** Ticks the LSQ. */ 737 void tick() { usedStorePorts = 0; } 738 739 /** Inserts a load into the LSQ. */ 740 void insertLoad(const DynInstPtr &load_inst); 741 /** Inserts a store into the LSQ. */ 742 void insertStore(const DynInstPtr &store_inst); 743 744 /** Executes a load. */ 745 Fault executeLoad(const DynInstPtr &inst); 746 747 /** Executes a store. */ 748 Fault executeStore(const DynInstPtr &inst); 749 750 /** 751 * Commits loads up until the given sequence number for a specific thread. 752 */ 753 void commitLoads(InstSeqNum &youngest_inst, ThreadID tid) 754 { thread.at(tid).commitLoads(youngest_inst); } 755 756 /** 757 * Commits stores up until the given sequence number for a specific thread. 758 */ 759 void commitStores(InstSeqNum &youngest_inst, ThreadID tid) 760 { thread.at(tid).commitStores(youngest_inst); } 761 762 /** 763 * Attempts to write back stores until all cache ports are used or the 764 * interface becomes blocked. 765 */ 766 void writebackStores(); 767 /** Same as above, but only for one thread. */ 768 void writebackStores(ThreadID tid); 769 770 /** 771 * Squash instructions from a thread until the specified sequence number. 772 */ 773 void 774 squash(const InstSeqNum &squashed_num, ThreadID tid) 775 { 776 thread.at(tid).squash(squashed_num); 777 } 778 779 /** Returns whether or not there was a memory ordering violation. */ 780 bool violation(); 781 /** 782 * Returns whether or not there was a memory ordering violation for a 783 * specific thread. 784 */ 785 bool violation(ThreadID tid) { return thread.at(tid).violation(); } 786 787 /** Gets the instruction that caused the memory ordering violation. */ 788 DynInstPtr 789 getMemDepViolator(ThreadID tid) 790 { 791 return thread.at(tid).getMemDepViolator(); 792 } 793 794 /** Returns the head index of the load queue for a specific thread. */ 795 int getLoadHead(ThreadID tid) { return thread.at(tid).getLoadHead(); } 796 797 /** Returns the sequence number of the head of the load queue. */ 798 InstSeqNum 799 getLoadHeadSeqNum(ThreadID tid) 800 { 801 return thread.at(tid).getLoadHeadSeqNum(); 802 } 803 804 /** Returns the head index of the store queue. */ 805 int getStoreHead(ThreadID tid) { return thread.at(tid).getStoreHead(); } 806 807 /** Returns the sequence number of the head of the store queue. */ 808 InstSeqNum 809 getStoreHeadSeqNum(ThreadID tid) 810 { 811 return thread.at(tid).getStoreHeadSeqNum(); 812 } 813 814 /** Returns the number of instructions in all of the queues. */ 815 int getCount(); 816 /** Returns the number of instructions in the queues of one thread. */ 817 int getCount(ThreadID tid) { return thread.at(tid).getCount(); } 818 819 /** Returns the total number of loads in the load queue. */ 820 int numLoads(); 821 /** Returns the total number of loads for a single thread. */ 822 int numLoads(ThreadID tid) { return thread.at(tid).numLoads(); } 823 824 /** Returns the total number of stores in the store queue. */ 825 int numStores(); 826 /** Returns the total number of stores for a single thread. */ 827 int numStores(ThreadID tid) { return thread.at(tid).numStores(); } 828 829 /** Returns the number of free load entries. */ 830 unsigned numFreeLoadEntries(); 831 832 /** Returns the number of free store entries. */ 833 unsigned numFreeStoreEntries(); 834 835 /** Returns the number of free entries for a specific thread. */ 836 unsigned numFreeEntries(ThreadID tid); 837 838 /** Returns the number of free entries in the LQ for a specific thread. */ 839 unsigned numFreeLoadEntries(ThreadID tid); 840 841 /** Returns the number of free entries in the SQ for a specific thread. */ 842 unsigned numFreeStoreEntries(ThreadID tid); 843 844 /** Returns if the LSQ is full (either LQ or SQ is full). */ 845 bool isFull(); 846 /** 847 * Returns if the LSQ is full for a specific thread (either LQ or SQ is 848 * full). 849 */ 850 bool isFull(ThreadID tid); 851 852 /** Returns if the LSQ is empty (both LQ and SQ are empty). */ 853 bool isEmpty() const; 854 /** Returns if all of the LQs are empty. */ 855 bool lqEmpty() const; 856 /** Returns if all of the SQs are empty. */ 857 bool sqEmpty() const; 858 859 /** Returns if any of the LQs are full. */ 860 bool lqFull(); 861 /** Returns if the LQ of a given thread is full. */ 862 bool lqFull(ThreadID tid); 863 864 /** Returns if any of the SQs are full. */ 865 bool sqFull(); 866 /** Returns if the SQ of a given thread is full. */ 867 bool sqFull(ThreadID tid); 868 869 /** 870 * Returns if the LSQ is stalled due to a memory operation that must be 871 * replayed. 872 */ 873 bool isStalled(); 874 /** 875 * Returns if the LSQ of a specific thread is stalled due to a memory 876 * operation that must be replayed. 877 */ 878 bool isStalled(ThreadID tid); 879 880 /** Returns whether or not there are any stores to write back to memory. */ 881 bool hasStoresToWB(); 882 883 /** Returns whether or not a specific thread has any stores to write back 884 * to memory. 885 */ 886 bool hasStoresToWB(ThreadID tid) { return thread.at(tid).hasStoresToWB(); } 887 888 /** Returns the number of stores a specific thread has to write back. */ 889 int numStoresToWB(ThreadID tid) { return thread.at(tid).numStoresToWB(); } 890 891 /** Returns if the LSQ will write back to memory this cycle. */ 892 bool willWB(); 893 /** Returns if the LSQ of a specific thread will write back to memory this 894 * cycle. 895 */ 896 bool willWB(ThreadID tid) { return thread.at(tid).willWB(); } 897 898 /** Debugging function to print out all instructions. */ 899 void dumpInsts() const; 900 /** Debugging function to print out instructions from a specific thread. */ 901 void dumpInsts(ThreadID tid) const { thread.at(tid).dumpInsts(); } 902 903 /** Executes a read operation, using the load specified at the load 904 * index. 905 */ 906 Fault read(LSQRequest* req, int load_idx); 907 908 /** Executes a store operation, using the store specified at the store 909 * index. 910 */ 911 Fault write(LSQRequest* req, uint8_t *data, int store_idx); 912 913 /** 914 * Retry the previous send that failed. 915 */ 916 void recvReqRetry(); 917 918 void completeDataAccess(PacketPtr pkt); 919 /** 920 * Handles writing back and completing the load or store that has 921 * returned from memory. 922 * 923 * @param pkt Response packet from the memory sub-system 924 */ 925 bool recvTimingResp(PacketPtr pkt); 926 927 void recvTimingSnoopReq(PacketPtr pkt); 928 929 Fault pushRequest(const DynInstPtr& inst, bool isLoad, uint8_t *data, 930 unsigned int size, Addr addr, Request::Flags flags, 931 uint64_t *res); 932 933 /** The CPU pointer. */ 934 O3CPU *cpu; 935 936 /** The IEW stage pointer. */ 937 IEW *iewStage; 938 939 /** Is D-cache blocked? */ 940 bool cacheBlocked() const; 941 /** Set D-cache blocked status */ 942 void cacheBlocked(bool v); 943 /** Is any store port available to use? */ 944 bool storePortAvailable() const; 945 /** Another store port is in use */ 946 void storePortBusy(); 947 948 protected: 949 /** D-cache is blocked */ 950 bool _cacheBlocked; 951 /** The number of cache ports available each cycle (stores only). */ 952 int cacheStorePorts; 953 /** The number of used cache ports in this cycle by stores. */ 954 int usedStorePorts; 955 956 957 /** The LSQ policy for SMT mode. */ 958 SMTQueuePolicy lsqPolicy; 959 960 /** Auxiliary function to calculate per-thread max LSQ allocation limit. 961 * Depending on a policy, number of entries and possibly number of threads 962 * and threshold, this function calculates how many resources each thread 963 * can occupy at most. 964 */ 965 static uint32_t 966 maxLSQAllocation(SMTQueuePolicy pol, uint32_t entries, 967 uint32_t numThreads, uint32_t SMTThreshold) 968 { 969 if (pol == SMTQueuePolicy::Dynamic) { 970 return entries; 971 } else if (pol == SMTQueuePolicy::Partitioned) { 972 //@todo:make work if part_amt doesnt divide evenly. 973 return entries / numThreads; 974 } else if (pol == SMTQueuePolicy::Threshold) { 975 //Divide up by threshold amount 976 //@todo: Should threads check the max and the total 977 //amount of the LSQ 978 return SMTThreshold; 979 } 980 return 0; 981 } 982 983 /** List of Active Threads in System. */ 984 std::list<ThreadID> *activeThreads; 985 986 /** Total Size of LQ Entries. */ 987 unsigned LQEntries; 988 /** Total Size of SQ Entries. */ 989 unsigned SQEntries; 990 991 /** Max LQ Size - Used to Enforce Sharing Policies. */ 992 unsigned maxLQEntries; 993 994 /** Max SQ Size - Used to Enforce Sharing Policies. */ 995 unsigned maxSQEntries; 996 997 /** The LSQ units for individual threads. */ 998 std::vector<LSQUnit> thread; 999 1000 /** Number of Threads. */ 1001 ThreadID numThreads; 1002}; 1003 1004template <class Impl> 1005Fault 1006LSQ<Impl>::read(LSQRequest* req, int load_idx) 1007{ 1008 ThreadID tid = cpu->contextToThread(req->request()->contextId()); 1009 1010 return thread.at(tid).read(req, load_idx); 1011} 1012 1013template <class Impl> 1014Fault 1015LSQ<Impl>::write(LSQRequest* req, uint8_t *data, int store_idx) 1016{ 1017 ThreadID tid = cpu->contextToThread(req->request()->contextId()); 1018 1019 return thread.at(tid).write(req, data, store_idx); 1020} 1021 1022#endif // __CPU_O3_LSQ_HH__ 1023