lsq.hh revision 13590:d7e018859709
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
57struct DerivO3CPUParams;
58
59template <class Impl>
60class 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 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
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. */
721    void regStats();
722
723    /** Sets the pointer to the list of active threads. */
724    void setActiveThreads(std::list<ThreadID> *at_ptr);
725
726    /** Perform sanity checks after a drain. */
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);
735
736    /** Ticks the LSQ. */
737    void tick() { usedStorePorts = 0; }
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)
754    { thread.at(tid).commitLoads(youngest_inst); }
755
756    /**
757     * Commits stores up until the given sequence number for a specific thread.
758     */
759    void commitStores(InstSeqNum &youngest_inst, ThreadID tid)
760    { thread.at(tid).commitStores(youngest_inst); }
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     */
773    void
774    squash(const InstSeqNum &squashed_num, ThreadID tid)
775    {
776        thread.at(tid).squash(squashed_num);
777    }
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     */
785    bool violation(ThreadID tid) { return thread.at(tid).violation(); }
786
787    /** Gets the instruction that caused the memory ordering violation. */
788    DynInstPtr
789    getMemDepViolator(ThreadID tid)
790    {
791        return thread.at(tid).getMemDepViolator();
792    }
793
794    /** Returns the head index of the load queue for a specific thread. */
795    int getLoadHead(ThreadID tid) { return thread.at(tid).getLoadHead(); }
796
797    /** Returns the sequence number of the head of the load queue. */
798    InstSeqNum
799    getLoadHeadSeqNum(ThreadID tid)
800    {
801        return thread.at(tid).getLoadHeadSeqNum();
802    }
803
804    /** Returns the head index of the store queue. */
805    int getStoreHead(ThreadID tid) { return thread.at(tid).getStoreHead(); }
806
807    /** Returns the sequence number of the head of the store queue. */
808    InstSeqNum
809    getStoreHeadSeqNum(ThreadID tid)
810    {
811        return thread.at(tid).getStoreHeadSeqNum();
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. */
817    int getCount(ThreadID tid) { return thread.at(tid).getCount(); }
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. */
822    int numLoads(ThreadID tid) { return thread.at(tid).numLoads(); }
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. */
827    int numStores(ThreadID tid) { return thread.at(tid).numStores(); }
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. */
836    unsigned numFreeEntries(ThreadID tid);
837
838    /** Returns the number of free entries in the LQ for a specific thread. */
839    unsigned numFreeLoadEntries(ThreadID tid);
840
841    /** Returns the number of free entries in the SQ for a specific thread. */
842    unsigned numFreeStoreEntries(ThreadID tid);
843
844    /** Returns if the LSQ is full (either LQ or SQ is full). */
845    bool isFull();
846    /**
847     * Returns if the LSQ is full for a specific thread (either LQ or SQ is
848     * full).
849     */
850    bool isFull(ThreadID tid);
851
852    /** Returns if the LSQ is empty (both LQ and SQ are empty). */
853    bool isEmpty() const;
854    /** Returns if all of the LQs are empty. */
855    bool lqEmpty() const;
856    /** Returns if all of the SQs are empty. */
857    bool sqEmpty() const;
858
859    /** Returns if any of the LQs are full. */
860    bool lqFull();
861    /** Returns if the LQ of a given thread is full. */
862    bool lqFull(ThreadID tid);
863
864    /** Returns if any of the SQs are full. */
865    bool sqFull();
866    /** Returns if the SQ of a given thread is full. */
867    bool sqFull(ThreadID tid);
868
869    /**
870     * Returns if the LSQ is stalled due to a memory operation that must be
871     * replayed.
872     */
873    bool isStalled();
874    /**
875     * Returns if the LSQ of a specific thread is stalled due to a memory
876     * operation that must be replayed.
877     */
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     */
886    bool hasStoresToWB(ThreadID tid) { return thread.at(tid).hasStoresToWB(); }
887
888    /** Returns the number of stores a specific thread has to write back. */
889    int numStoresToWB(ThreadID tid) { return thread.at(tid).numStoresToWB(); }
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     */
896    bool willWB(ThreadID tid) { return thread.at(tid).willWB(); }
897
898    /** Debugging function to print out all instructions. */
899    void dumpInsts() const;
900    /** Debugging function to print out instructions from a specific thread. */
901    void dumpInsts(ThreadID tid) const { thread.at(tid).dumpInsts(); }
902
903    /** Executes a read operation, using the load specified at the load
904     * index.
905     */
906    Fault read(LSQRequest* req, int load_idx);
907
908    /** Executes a store operation, using the store specified at the store
909     * index.
910     */
911    Fault write(LSQRequest* req, uint8_t *data, int store_idx);
912
913    /**
914     * Retry the previous send that failed.
915     */
916    void recvReqRetry();
917
918    void completeDataAccess(PacketPtr pkt);
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
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
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
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     */
965    static uint32_t
966    maxLSQAllocation(SMTQueuePolicy pol, uint32_t entries,
967            uint32_t numThreads, uint32_t SMTThreshold)
968    {
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
977            //amount of the LSQ
978            return SMTThreshold;
979        }
980        return 0;
981    }
982
983    /** List of Active Threads in System. */
984    std::list<ThreadID> *activeThreads;
985
986    /** Total Size of LQ Entries. */
987    unsigned LQEntries;
988    /** Total Size of SQ Entries. */
989    unsigned SQEntries;
990
991    /** Max LQ Size - Used to Enforce Sharing Policies. */
992    unsigned maxLQEntries;
993
994    /** Max SQ Size - Used to Enforce Sharing Policies. */
995    unsigned maxSQEntries;
996
997    /** The LSQ units for individual threads. */
998    std::vector<LSQUnit> thread;
999
1000    /** Number of Threads. */
1001    ThreadID numThreads;
1002};
1003
1004template <class Impl>
1005Fault
1006LSQ<Impl>::read(LSQRequest* req, int load_idx)
1007{
1008    ThreadID tid = cpu->contextToThread(req->request()->contextId());
1009
1010    return thread.at(tid).read(req, load_idx);
1011}
1012
1013template <class Impl>
1014Fault
1015LSQ<Impl>::write(LSQRequest* req, uint8_t *data, int store_idx)
1016{
1017    ThreadID tid = cpu->contextToThread(req->request()->contextId());
1018
1019    return thread.at(tid).write(req, data, store_idx);
1020}
1021
1022#endif // __CPU_O3_LSQ_HH__
1023