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