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