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