lsq.hh revision 13710:5ba1d8066ef0
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/atomic 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 /** True if this is an atomic request */ 216 IsAtomic = 0x00004000 217 }; 218 FlagsType flags; 219 220 enum class State 221 { 222 NotIssued, 223 Translation, 224 Request, 225 Complete, 226 Squashed, 227 Fault, 228 }; 229 State _state; 230 LSQSenderState* _senderState; 231 void setState(const State& newState) { _state = newState; } 232 233 uint32_t numTranslatedFragments; 234 uint32_t numInTranslationFragments; 235 236 /** LQ/SQ entry idx. */ 237 uint32_t _entryIdx; 238 239 void markDelayed() override { flags.set(Flag::Delayed); } 240 bool isDelayed() { return flags.isSet(Flag::Delayed); } 241 242 public: 243 LSQUnit& _port; 244 const DynInstPtr _inst; 245 uint32_t _taskId; 246 PacketDataPtr _data; 247 std::vector<PacketPtr> _packets; 248 std::vector<RequestPtr> _requests; 249 std::vector<Fault> _fault; 250 uint64_t* _res; 251 const Addr _addr; 252 const uint32_t _size; 253 const Request::Flags _flags; 254 uint32_t _numOutstandingPackets; 255 AtomicOpFunctor *_amo_op; 256 protected: 257 LSQUnit* lsqUnit() { return &_port; } 258 LSQRequest(LSQUnit* port, const DynInstPtr& inst, bool isLoad) : 259 _state(State::NotIssued), _senderState(nullptr), 260 _port(*port), _inst(inst), _data(nullptr), 261 _res(nullptr), _addr(0), _size(0), _flags(0), 262 _numOutstandingPackets(0), _amo_op(nullptr) 263 { 264 flags.set(Flag::IsLoad, isLoad); 265 flags.set(Flag::WbStore, 266 _inst->isStoreConditional() || _inst->isAtomic()); 267 flags.set(Flag::IsAtomic, _inst->isAtomic()); 268 install(); 269 } 270 LSQRequest(LSQUnit* port, const DynInstPtr& inst, bool isLoad, 271 const Addr& addr, const uint32_t& size, 272 const Request::Flags& flags_, 273 PacketDataPtr data = nullptr, uint64_t* res = nullptr, 274 AtomicOpFunctor* amo_op = nullptr) 275 : _state(State::NotIssued), _senderState(nullptr), 276 numTranslatedFragments(0), 277 numInTranslationFragments(0), 278 _port(*port), _inst(inst), _data(data), 279 _res(res), _addr(addr), _size(size), 280 _flags(flags_), 281 _numOutstandingPackets(0), 282 _amo_op(amo_op) 283 { 284 flags.set(Flag::IsLoad, isLoad); 285 flags.set(Flag::WbStore, 286 _inst->isStoreConditional() || _inst->isAtomic()); 287 flags.set(Flag::IsAtomic, _inst->isAtomic()); 288 install(); 289 } 290 291 bool 292 isLoad() const 293 { 294 return flags.isSet(Flag::IsLoad); 295 } 296 297 bool 298 isAtomic() const 299 { 300 return flags.isSet(Flag::IsAtomic); 301 } 302 303 /** Install the request in the LQ/SQ. */ 304 void install() 305 { 306 if (isLoad()) { 307 _port.loadQueue[_inst->lqIdx].setRequest(this); 308 } else { 309 // Store, StoreConditional, and Atomic requests are pushed 310 // to this storeQueue 311 _port.storeQueue[_inst->sqIdx].setRequest(this); 312 } 313 } 314 virtual bool 315 squashed() const override 316 { 317 return _inst->isSquashed(); 318 } 319 320 /** 321 * Test if the LSQRequest has been released, i.e. self-owned. 322 * An LSQRequest manages itself when the resources on the LSQ are freed 323 * but the translation is still going on and the LSQEntry was freed. 324 */ 325 bool 326 isReleased() 327 { 328 return flags.isSet(Flag::LSQEntryFreed) || 329 flags.isSet(Flag::Discarded); 330 } 331 332 /** Release the LSQRequest. 333 * Notify the sender state that the request it points to is not valid 334 * anymore. Understand if the request is orphan (self-managed) and if 335 * so, mark it as freed, else destroy it, as this means 336 * the end of its life cycle. 337 * An LSQRequest is orphan when its resources are released 338 * but there is any in-flight translation request to the TLB or access 339 * request to the memory. 340 */ 341 void release(Flag reason) 342 { 343 assert(reason == Flag::LSQEntryFreed || reason == Flag::Discarded); 344 if (!isAnyOutstandingRequest()) { 345 delete this; 346 } else { 347 if (_senderState) { 348 _senderState->deleteRequest(); 349 } 350 flags.set(reason); 351 } 352 } 353 354 /** Destructor. 355 * The LSQRequest owns the request. If the packet has already been 356 * sent, the sender state will be deleted upon receiving the reply. 357 */ 358 virtual ~LSQRequest() 359 { 360 assert(!isAnyOutstandingRequest()); 361 _inst->savedReq = nullptr; 362 if (_senderState) 363 delete _senderState; 364 365 for (auto r: _packets) 366 delete r; 367 }; 368 369 370 public: 371 /** Convenience getters/setters. */ 372 /** @{ */ 373 /** Set up Context numbers. */ 374 void 375 setContext(const ContextID& context_id) 376 { 377 request()->setContext(context_id); 378 } 379 380 const DynInstPtr& 381 instruction() 382 { 383 return _inst; 384 } 385 386 /** Set up virtual request. 387 * For a previously allocated Request objects. 388 */ 389 void 390 setVirt(int asid, Addr vaddr, unsigned size, Request::Flags flags_, 391 MasterID mid, Addr pc) 392 { 393 request()->setVirt(asid, vaddr, size, flags_, mid, pc); 394 } 395 396 void 397 taskId(const uint32_t& v) 398 { 399 _taskId = v; 400 for (auto& r: _requests) 401 r->taskId(v); 402 } 403 404 uint32_t taskId() const { return _taskId; } 405 RequestPtr request(int idx = 0) { return _requests.at(idx); } 406 407 const RequestPtr 408 request(int idx = 0) const 409 { 410 return _requests.at(idx); 411 } 412 413 Addr getVaddr(int idx = 0) const { return request(idx)->getVaddr(); } 414 virtual void initiateTranslation() = 0; 415 416 PacketPtr packet(int idx = 0) { return _packets.at(idx); } 417 418 virtual PacketPtr 419 mainPacket() 420 { 421 assert (_packets.size() == 1); 422 return packet(); 423 } 424 425 virtual RequestPtr 426 mainRequest() 427 { 428 assert (_requests.size() == 1); 429 return request(); 430 } 431 432 void 433 senderState(LSQSenderState* st) 434 { 435 _senderState = st; 436 for (auto& pkt: _packets) { 437 if (pkt) 438 pkt->senderState = st; 439 } 440 } 441 442 const LSQSenderState* 443 senderState() const 444 { 445 return _senderState; 446 } 447 448 /** 449 * Mark senderState as discarded. This will cause to discard response 450 * packets from the cache. 451 */ 452 void 453 discardSenderState() 454 { 455 assert(_senderState); 456 _senderState->deleteRequest(); 457 } 458 459 /** 460 * Test if there is any in-flight translation or mem access request 461 */ 462 bool 463 isAnyOutstandingRequest() 464 { 465 return numInTranslationFragments > 0 || 466 _numOutstandingPackets > 0 || 467 (flags.isSet(Flag::WritebackScheduled) && 468 !flags.isSet(Flag::WritebackDone)); 469 } 470 471 bool 472 isSplit() const 473 { 474 return flags.isSet(Flag::IsSplit); 475 } 476 /** @} */ 477 virtual bool recvTimingResp(PacketPtr pkt) = 0; 478 virtual void sendPacketToCache() = 0; 479 virtual void buildPackets() = 0; 480 481 /** 482 * Memory mapped IPR accesses 483 */ 484 virtual void handleIprWrite(ThreadContext *thread, PacketPtr pkt) = 0; 485 virtual Cycles handleIprRead(ThreadContext *thread, PacketPtr pkt) = 0; 486 487 /** 488 * Test if the request accesses a particular cache line. 489 */ 490 virtual bool isCacheBlockHit(Addr blockAddr, Addr cacheBlockMask) = 0; 491 492 /** Update the status to reflect that a packet was sent. */ 493 void 494 packetSent() 495 { 496 flags.set(Flag::Sent); 497 } 498 /** Update the status to reflect that a packet was not sent. 499 * When a packet fails to be sent, we mark the request as needing a 500 * retry. Note that Retry flag is sticky. 501 */ 502 void 503 packetNotSent() 504 { 505 flags.set(Flag::Retry); 506 flags.clear(Flag::Sent); 507 } 508 509 void sendFragmentToTranslation(int i); 510 bool 511 isComplete() 512 { 513 return flags.isSet(Flag::Complete); 514 } 515 516 bool 517 isInTranslation() 518 { 519 return _state == State::Translation; 520 } 521 522 bool 523 isTranslationComplete() 524 { 525 return flags.isSet(Flag::TranslationStarted) && 526 !isInTranslation(); 527 } 528 529 bool 530 isTranslationBlocked() 531 { 532 return _state == State::Translation && 533 flags.isSet(Flag::TranslationStarted) && 534 !flags.isSet(Flag::TranslationFinished); 535 } 536 537 bool 538 isSent() 539 { 540 return flags.isSet(Flag::Sent); 541 } 542 543 /** 544 * The LSQ entry is cleared 545 */ 546 void 547 freeLSQEntry() 548 { 549 release(Flag::LSQEntryFreed); 550 } 551 552 /** 553 * The request is discarded (e.g. partial store-load forwarding) 554 */ 555 void 556 discard() 557 { 558 release(Flag::Discarded); 559 } 560 561 void 562 packetReplied() 563 { 564 assert(_numOutstandingPackets > 0); 565 _numOutstandingPackets--; 566 if (_numOutstandingPackets == 0 && isReleased()) 567 delete this; 568 } 569 570 void 571 writebackScheduled() 572 { 573 assert(!flags.isSet(Flag::WritebackScheduled)); 574 flags.set(Flag::WritebackScheduled); 575 } 576 577 void 578 writebackDone() 579 { 580 flags.set(Flag::WritebackDone); 581 /* If the lsq resources are already free */ 582 if (isReleased()) { 583 delete this; 584 } 585 } 586 587 void 588 squashTranslation() 589 { 590 assert(numInTranslationFragments == 0); 591 flags.set(Flag::TranslationSquashed); 592 /* If we are on our own, self-destruct. */ 593 if (isReleased()) { 594 delete this; 595 } 596 } 597 598 void 599 complete() 600 { 601 flags.set(Flag::Complete); 602 } 603 }; 604 605 class SingleDataRequest : public LSQRequest 606 { 607 protected: 608 /* Given that we are inside templates, children need explicit 609 * declaration of the names in the parent class. */ 610 using Flag = typename LSQRequest::Flag; 611 using State = typename LSQRequest::State; 612 using LSQRequest::_fault; 613 using LSQRequest::_inst; 614 using LSQRequest::_packets; 615 using LSQRequest::_port; 616 using LSQRequest::_res; 617 using LSQRequest::_senderState; 618 using LSQRequest::_state; 619 using LSQRequest::flags; 620 using LSQRequest::isLoad; 621 using LSQRequest::isTranslationComplete; 622 using LSQRequest::lsqUnit; 623 using LSQRequest::request; 624 using LSQRequest::sendFragmentToTranslation; 625 using LSQRequest::setState; 626 using LSQRequest::numInTranslationFragments; 627 using LSQRequest::numTranslatedFragments; 628 using LSQRequest::_numOutstandingPackets; 629 using LSQRequest::_amo_op; 630 public: 631 SingleDataRequest(LSQUnit* port, const DynInstPtr& inst, bool isLoad, 632 const Addr& addr, const uint32_t& size, 633 const Request::Flags& flags_, 634 PacketDataPtr data = nullptr, 635 uint64_t* res = nullptr, 636 AtomicOpFunctor* amo_op = nullptr) : 637 LSQRequest(port, inst, isLoad, addr, size, flags_, data, res, 638 amo_op) 639 { 640 LSQRequest::_requests.push_back( 641 std::make_shared<Request>(inst->getASID(), addr, size, 642 flags_, inst->masterId(), inst->instAddr(), 643 inst->contextId(), amo_op)); 644 LSQRequest::_requests.back()->setReqInstSeqNum(inst->seqNum); 645 } 646 inline virtual ~SingleDataRequest() {} 647 virtual void initiateTranslation(); 648 virtual void finish(const Fault &fault, const RequestPtr &req, 649 ThreadContext* tc, BaseTLB::Mode mode); 650 virtual bool recvTimingResp(PacketPtr pkt); 651 virtual void sendPacketToCache(); 652 virtual void buildPackets(); 653 virtual void handleIprWrite(ThreadContext *thread, PacketPtr pkt); 654 virtual Cycles handleIprRead(ThreadContext *thread, PacketPtr pkt); 655 virtual bool isCacheBlockHit(Addr blockAddr, Addr cacheBlockMask); 656 }; 657 658 class SplitDataRequest : public LSQRequest 659 { 660 protected: 661 /* Given that we are inside templates, children need explicit 662 * declaration of the names in the parent class. */ 663 using Flag = typename LSQRequest::Flag; 664 using State = typename LSQRequest::State; 665 using LSQRequest::_addr; 666 using LSQRequest::_data; 667 using LSQRequest::_fault; 668 using LSQRequest::_flags; 669 using LSQRequest::_inst; 670 using LSQRequest::_packets; 671 using LSQRequest::_port; 672 using LSQRequest::_requests; 673 using LSQRequest::_res; 674 using LSQRequest::_senderState; 675 using LSQRequest::_size; 676 using LSQRequest::_state; 677 using LSQRequest::_taskId; 678 using LSQRequest::flags; 679 using LSQRequest::isLoad; 680 using LSQRequest::isTranslationComplete; 681 using LSQRequest::lsqUnit; 682 using LSQRequest::numInTranslationFragments; 683 using LSQRequest::numTranslatedFragments; 684 using LSQRequest::request; 685 using LSQRequest::sendFragmentToTranslation; 686 using LSQRequest::setState; 687 using LSQRequest::_numOutstandingPackets; 688 689 uint32_t numFragments; 690 uint32_t numReceivedPackets; 691 RequestPtr mainReq; 692 PacketPtr _mainPacket; 693 694 695 public: 696 SplitDataRequest(LSQUnit* port, const DynInstPtr& inst, bool isLoad, 697 const Addr& addr, const uint32_t& size, 698 const Request::Flags & flags_, 699 PacketDataPtr data = nullptr, 700 uint64_t* res = nullptr) : 701 LSQRequest(port, inst, isLoad, addr, size, flags_, data, res), 702 numFragments(0), 703 numReceivedPackets(0), 704 mainReq(nullptr), 705 _mainPacket(nullptr) 706 { 707 flags.set(Flag::IsSplit); 708 } 709 virtual ~SplitDataRequest() 710 { 711 if (mainReq) { 712 mainReq = nullptr; 713 } 714 if (_mainPacket) { 715 delete _mainPacket; 716 _mainPacket = nullptr; 717 } 718 } 719 virtual void finish(const Fault &fault, const RequestPtr &req, 720 ThreadContext* tc, BaseTLB::Mode mode); 721 virtual bool recvTimingResp(PacketPtr pkt); 722 virtual void initiateTranslation(); 723 virtual void sendPacketToCache(); 724 virtual void buildPackets(); 725 726 virtual void handleIprWrite(ThreadContext *thread, PacketPtr pkt); 727 virtual Cycles handleIprRead(ThreadContext *thread, PacketPtr pkt); 728 virtual bool isCacheBlockHit(Addr blockAddr, Addr cacheBlockMask); 729 730 virtual RequestPtr mainRequest(); 731 virtual PacketPtr mainPacket(); 732 }; 733 734 /** Constructs an LSQ with the given parameters. */ 735 LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params); 736 ~LSQ() { } 737 738 /** Returns the name of the LSQ. */ 739 std::string name() const; 740 741 /** Registers statistics of each LSQ unit. */ 742 void regStats(); 743 744 /** Sets the pointer to the list of active threads. */ 745 void setActiveThreads(std::list<ThreadID> *at_ptr); 746 747 /** Perform sanity checks after a drain. */ 748 void drainSanityCheck() const; 749 /** Has the LSQ drained? */ 750 bool isDrained() const; 751 /** Takes over execution from another CPU's thread. */ 752 void takeOverFrom(); 753 754 /** Number of entries needed for the given amount of threads.*/ 755 int entryAmount(ThreadID num_threads); 756 757 /** Ticks the LSQ. */ 758 void tick(); 759 760 /** Inserts a load into the LSQ. */ 761 void insertLoad(const DynInstPtr &load_inst); 762 /** Inserts a store into the LSQ. */ 763 void insertStore(const DynInstPtr &store_inst); 764 765 /** Executes a load. */ 766 Fault executeLoad(const DynInstPtr &inst); 767 768 /** Executes a store. */ 769 Fault executeStore(const DynInstPtr &inst); 770 771 /** 772 * Commits loads up until the given sequence number for a specific thread. 773 */ 774 void commitLoads(InstSeqNum &youngest_inst, ThreadID tid) 775 { thread.at(tid).commitLoads(youngest_inst); } 776 777 /** 778 * Commits stores up until the given sequence number for a specific thread. 779 */ 780 void commitStores(InstSeqNum &youngest_inst, ThreadID tid) 781 { thread.at(tid).commitStores(youngest_inst); } 782 783 /** 784 * Attempts to write back stores until all cache ports are used or the 785 * interface becomes blocked. 786 */ 787 void writebackStores(); 788 /** Same as above, but only for one thread. */ 789 void writebackStores(ThreadID tid); 790 791 /** 792 * Squash instructions from a thread until the specified sequence number. 793 */ 794 void 795 squash(const InstSeqNum &squashed_num, ThreadID tid) 796 { 797 thread.at(tid).squash(squashed_num); 798 } 799 800 /** Returns whether or not there was a memory ordering violation. */ 801 bool violation(); 802 /** 803 * Returns whether or not there was a memory ordering violation for a 804 * specific thread. 805 */ 806 bool violation(ThreadID tid) { return thread.at(tid).violation(); } 807 808 /** Gets the instruction that caused the memory ordering violation. */ 809 DynInstPtr 810 getMemDepViolator(ThreadID tid) 811 { 812 return thread.at(tid).getMemDepViolator(); 813 } 814 815 /** Returns the head index of the load queue for a specific thread. */ 816 int getLoadHead(ThreadID tid) { return thread.at(tid).getLoadHead(); } 817 818 /** Returns the sequence number of the head of the load queue. */ 819 InstSeqNum 820 getLoadHeadSeqNum(ThreadID tid) 821 { 822 return thread.at(tid).getLoadHeadSeqNum(); 823 } 824 825 /** Returns the head index of the store queue. */ 826 int getStoreHead(ThreadID tid) { return thread.at(tid).getStoreHead(); } 827 828 /** Returns the sequence number of the head of the store queue. */ 829 InstSeqNum 830 getStoreHeadSeqNum(ThreadID tid) 831 { 832 return thread.at(tid).getStoreHeadSeqNum(); 833 } 834 835 /** Returns the number of instructions in all of the queues. */ 836 int getCount(); 837 /** Returns the number of instructions in the queues of one thread. */ 838 int getCount(ThreadID tid) { return thread.at(tid).getCount(); } 839 840 /** Returns the total number of loads in the load queue. */ 841 int numLoads(); 842 /** Returns the total number of loads for a single thread. */ 843 int numLoads(ThreadID tid) { return thread.at(tid).numLoads(); } 844 845 /** Returns the total number of stores in the store queue. */ 846 int numStores(); 847 /** Returns the total number of stores for a single thread. */ 848 int numStores(ThreadID tid) { return thread.at(tid).numStores(); } 849 850 /** Returns the number of free load entries. */ 851 unsigned numFreeLoadEntries(); 852 853 /** Returns the number of free store entries. */ 854 unsigned numFreeStoreEntries(); 855 856 /** Returns the number of free entries for a specific thread. */ 857 unsigned numFreeEntries(ThreadID tid); 858 859 /** Returns the number of free entries in the LQ for a specific thread. */ 860 unsigned numFreeLoadEntries(ThreadID tid); 861 862 /** Returns the number of free entries in the SQ for a specific thread. */ 863 unsigned numFreeStoreEntries(ThreadID tid); 864 865 /** Returns if the LSQ is full (either LQ or SQ is full). */ 866 bool isFull(); 867 /** 868 * Returns if the LSQ is full for a specific thread (either LQ or SQ is 869 * full). 870 */ 871 bool isFull(ThreadID tid); 872 873 /** Returns if the LSQ is empty (both LQ and SQ are empty). */ 874 bool isEmpty() const; 875 /** Returns if all of the LQs are empty. */ 876 bool lqEmpty() const; 877 /** Returns if all of the SQs are empty. */ 878 bool sqEmpty() const; 879 880 /** Returns if any of the LQs are full. */ 881 bool lqFull(); 882 /** Returns if the LQ of a given thread is full. */ 883 bool lqFull(ThreadID tid); 884 885 /** Returns if any of the SQs are full. */ 886 bool sqFull(); 887 /** Returns if the SQ of a given thread is full. */ 888 bool sqFull(ThreadID tid); 889 890 /** 891 * Returns if the LSQ is stalled due to a memory operation that must be 892 * replayed. 893 */ 894 bool isStalled(); 895 /** 896 * Returns if the LSQ of a specific thread is stalled due to a memory 897 * operation that must be replayed. 898 */ 899 bool isStalled(ThreadID tid); 900 901 /** Returns whether or not there are any stores to write back to memory. */ 902 bool hasStoresToWB(); 903 904 /** Returns whether or not a specific thread has any stores to write back 905 * to memory. 906 */ 907 bool hasStoresToWB(ThreadID tid) { return thread.at(tid).hasStoresToWB(); } 908 909 /** Returns the number of stores a specific thread has to write back. */ 910 int numStoresToWB(ThreadID tid) { return thread.at(tid).numStoresToWB(); } 911 912 /** Returns if the LSQ will write back to memory this cycle. */ 913 bool willWB(); 914 /** Returns if the LSQ of a specific thread will write back to memory this 915 * cycle. 916 */ 917 bool willWB(ThreadID tid) { return thread.at(tid).willWB(); } 918 919 /** Debugging function to print out all instructions. */ 920 void dumpInsts() const; 921 /** Debugging function to print out instructions from a specific thread. */ 922 void dumpInsts(ThreadID tid) const { thread.at(tid).dumpInsts(); } 923 924 /** Executes a read operation, using the load specified at the load 925 * index. 926 */ 927 Fault read(LSQRequest* req, int load_idx); 928 929 /** Executes a store operation, using the store specified at the store 930 * index. 931 */ 932 Fault write(LSQRequest* req, uint8_t *data, int store_idx); 933 934 /** 935 * Retry the previous send that failed. 936 */ 937 void recvReqRetry(); 938 939 void completeDataAccess(PacketPtr pkt); 940 /** 941 * Handles writing back and completing the load or store that has 942 * returned from memory. 943 * 944 * @param pkt Response packet from the memory sub-system 945 */ 946 bool recvTimingResp(PacketPtr pkt); 947 948 void recvTimingSnoopReq(PacketPtr pkt); 949 950 Fault pushRequest(const DynInstPtr& inst, bool isLoad, uint8_t *data, 951 unsigned int size, Addr addr, Request::Flags flags, 952 uint64_t *res, AtomicOpFunctor *amo_op); 953 954 /** The CPU pointer. */ 955 O3CPU *cpu; 956 957 /** The IEW stage pointer. */ 958 IEW *iewStage; 959 960 /** Is D-cache blocked? */ 961 bool cacheBlocked() const; 962 /** Set D-cache blocked status */ 963 void cacheBlocked(bool v); 964 /** Is any store port available to use? */ 965 bool cachePortAvailable(bool is_load) const; 966 /** Another store port is in use */ 967 void cachePortBusy(bool is_load); 968 969 protected: 970 /** D-cache is blocked */ 971 bool _cacheBlocked; 972 /** The number of cache ports available each cycle (stores only). */ 973 int cacheStorePorts; 974 /** The number of used cache ports in this cycle by stores. */ 975 int usedStorePorts; 976 /** The number of cache ports available each cycle (loads only). */ 977 int cacheLoadPorts; 978 /** The number of used cache ports in this cycle by loads. */ 979 int usedLoadPorts; 980 981 982 /** The LSQ policy for SMT mode. */ 983 SMTQueuePolicy lsqPolicy; 984 985 /** Auxiliary function to calculate per-thread max LSQ allocation limit. 986 * Depending on a policy, number of entries and possibly number of threads 987 * and threshold, this function calculates how many resources each thread 988 * can occupy at most. 989 */ 990 static uint32_t 991 maxLSQAllocation(SMTQueuePolicy pol, uint32_t entries, 992 uint32_t numThreads, uint32_t SMTThreshold) 993 { 994 if (pol == SMTQueuePolicy::Dynamic) { 995 return entries; 996 } else if (pol == SMTQueuePolicy::Partitioned) { 997 //@todo:make work if part_amt doesnt divide evenly. 998 return entries / numThreads; 999 } else if (pol == SMTQueuePolicy::Threshold) { 1000 //Divide up by threshold amount 1001 //@todo: Should threads check the max and the total 1002 //amount of the LSQ 1003 return SMTThreshold; 1004 } 1005 return 0; 1006 } 1007 1008 /** List of Active Threads in System. */ 1009 std::list<ThreadID> *activeThreads; 1010 1011 /** Total Size of LQ Entries. */ 1012 unsigned LQEntries; 1013 /** Total Size of SQ Entries. */ 1014 unsigned SQEntries; 1015 1016 /** Max LQ Size - Used to Enforce Sharing Policies. */ 1017 unsigned maxLQEntries; 1018 1019 /** Max SQ Size - Used to Enforce Sharing Policies. */ 1020 unsigned maxSQEntries; 1021 1022 /** The LSQ units for individual threads. */ 1023 std::vector<LSQUnit> thread; 1024 1025 /** Number of Threads. */ 1026 ThreadID numThreads; 1027}; 1028 1029template <class Impl> 1030Fault 1031LSQ<Impl>::read(LSQRequest* req, int load_idx) 1032{ 1033 ThreadID tid = cpu->contextToThread(req->request()->contextId()); 1034 1035 return thread.at(tid).read(req, load_idx); 1036} 1037 1038template <class Impl> 1039Fault 1040LSQ<Impl>::write(LSQRequest* req, uint8_t *data, int store_idx) 1041{ 1042 ThreadID tid = cpu->contextToThread(req->request()->contextId()); 1043 1044 return thread.at(tid).write(req, data, store_idx); 1045} 1046 1047#endif // __CPU_O3_LSQ_HH__ 1048