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