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