lsq.hh revision 13710:5ba1d8066ef0
17404SAli.Saidi@ARM.com/*
27404SAli.Saidi@ARM.com * Copyright (c) 2011-2012, 2014, 2018 ARM Limited
37404SAli.Saidi@ARM.com * Copyright (c) 2013 Advanced Micro Devices, Inc.
47404SAli.Saidi@ARM.com * All rights reserved
57404SAli.Saidi@ARM.com *
67404SAli.Saidi@ARM.com * The license below extends only to copyright in the software and shall
77404SAli.Saidi@ARM.com * not be construed as granting a license to any other intellectual
87404SAli.Saidi@ARM.com * property including but not limited to intellectual property relating
97404SAli.Saidi@ARM.com * to a hardware implementation of the functionality of the software
107404SAli.Saidi@ARM.com * licensed hereunder.  You may use the software subject to the license
117404SAli.Saidi@ARM.com * terms below provided that you ensure that this notice is replicated
127404SAli.Saidi@ARM.com * unmodified and in its entirety in all distributions of the software,
137404SAli.Saidi@ARM.com * modified or unmodified, in source code or in binary form.
147404SAli.Saidi@ARM.com *
157404SAli.Saidi@ARM.com * Copyright (c) 2004-2006 The Regents of The University of Michigan
167404SAli.Saidi@ARM.com * All rights reserved.
177404SAli.Saidi@ARM.com *
187404SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without
197404SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are
207404SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright
217404SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer;
227404SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright
237404SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the
247404SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution;
257404SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its
267404SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from
277404SAli.Saidi@ARM.com * this software without specific prior written permission.
287404SAli.Saidi@ARM.com *
297404SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
307404SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
317404SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
327404SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
337404SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
347404SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
357404SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
367404SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
377404SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
387404SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
397404SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
407404SAli.Saidi@ARM.com *
417404SAli.Saidi@ARM.com * Authors: Korey Sewell
427404SAli.Saidi@ARM.com */
437578Sdam.sunwoo@arm.com
447578Sdam.sunwoo@arm.com#ifndef __CPU_O3_LSQ_HH__
457404SAli.Saidi@ARM.com#define __CPU_O3_LSQ_HH__
467404SAli.Saidi@ARM.com
478851Sandreas.hansson@arm.com#include <map>
487404SAli.Saidi@ARM.com#include <queue>
497404SAli.Saidi@ARM.com
507404SAli.Saidi@ARM.com#include "arch/generic/tlb.hh"
517404SAli.Saidi@ARM.com#include "cpu/inst_seq.hh"
527878Sgblack@eecs.umich.edu#include "cpu/o3/lsq_unit.hh"
537404SAli.Saidi@ARM.com#include "enums/SMTQueuePolicy.hh"
547404SAli.Saidi@ARM.com#include "mem/port.hh"
557404SAli.Saidi@ARM.com#include "sim/sim_object.hh"
567404SAli.Saidi@ARM.com
577404SAli.Saidi@ARM.comstruct DerivO3CPUParams;
587404SAli.Saidi@ARM.com
597404SAli.Saidi@ARM.comtemplate <class Impl>
607404SAli.Saidi@ARM.comclass LSQ
617404SAli.Saidi@ARM.com
627404SAli.Saidi@ARM.com{
637694SAli.Saidi@ARM.com  public:
647404SAli.Saidi@ARM.com    typedef typename Impl::O3CPU O3CPU;
657404SAli.Saidi@ARM.com    typedef typename Impl::DynInstPtr DynInstPtr;
667404SAli.Saidi@ARM.com    typedef typename Impl::CPUPol::IEW IEW;
677404SAli.Saidi@ARM.com    typedef typename Impl::CPUPol::LSQUnit LSQUnit;
687404SAli.Saidi@ARM.com
697404SAli.Saidi@ARM.com    class LSQRequest;
707404SAli.Saidi@ARM.com    /** Derived class to hold any sender state the LSQ needs. */
717404SAli.Saidi@ARM.com    class LSQSenderState : public Packet::SenderState
727404SAli.Saidi@ARM.com    {
737436Sdam.sunwoo@arm.com      protected:
747404SAli.Saidi@ARM.com        /** The senderState needs to know the LSQRequest who owns it. */
757404SAli.Saidi@ARM.com        LSQRequest* _request;
767436Sdam.sunwoo@arm.com
777436Sdam.sunwoo@arm.com        /** Default constructor. */
787436Sdam.sunwoo@arm.com        LSQSenderState(LSQRequest* request, bool isLoad_)
797436Sdam.sunwoo@arm.com            : _request(request), mainPkt(nullptr), pendingPacket(nullptr),
807404SAli.Saidi@ARM.com              outstanding(0), isLoad(isLoad_), needWB(isLoad_), isSplit(false),
817404SAli.Saidi@ARM.com              pktToSend(false), deleted(false)
827404SAli.Saidi@ARM.com          { }
837404SAli.Saidi@ARM.com      public:
847404SAli.Saidi@ARM.com
857404SAli.Saidi@ARM.com        /** Instruction which initiated the access to memory. */
867404SAli.Saidi@ARM.com        DynInstPtr inst;
877404SAli.Saidi@ARM.com        /** The main packet from a split load, used during writeback. */
887404SAli.Saidi@ARM.com        PacketPtr mainPkt;
897404SAli.Saidi@ARM.com        /** A second packet from a split store that needs sending. */
907404SAli.Saidi@ARM.com        PacketPtr pendingPacket;
917404SAli.Saidi@ARM.com        /** Number of outstanding packets to complete. */
927404SAli.Saidi@ARM.com        uint8_t outstanding;
937404SAli.Saidi@ARM.com        /** Whether or not it is a load. */
947404SAli.Saidi@ARM.com        bool isLoad;
957404SAli.Saidi@ARM.com        /** Whether or not the instruction will need to writeback. */
967946SGiacomo.Gabrielli@arm.com        bool needWB;
977404SAli.Saidi@ARM.com        /** Whether or not this access is split in two. */
987694SAli.Saidi@ARM.com        bool isSplit;
997694SAli.Saidi@ARM.com        /** Whether or not there is a packet that needs sending. */
1007694SAli.Saidi@ARM.com        bool pktToSend;
1017694SAli.Saidi@ARM.com        /** Has the request been deleted?
1027694SAli.Saidi@ARM.com         * LSQ entries can be squashed before the response comes back. in that
1037946SGiacomo.Gabrielli@arm.com         * case the SenderState knows.
1047694SAli.Saidi@ARM.com         */
1057694SAli.Saidi@ARM.com        bool deleted;
1067404SAli.Saidi@ARM.com        ContextID contextId() { return inst->contextId(); }
1077404SAli.Saidi@ARM.com
1087404SAli.Saidi@ARM.com        /** Completes a packet and returns whether the access is finished. */
1097404SAli.Saidi@ARM.com        inline bool isComplete() { return outstanding == 0; }
1107404SAli.Saidi@ARM.com        inline void deleteRequest() { deleted = true; }
1117404SAli.Saidi@ARM.com        inline bool alive() { return !deleted; }
1127946SGiacomo.Gabrielli@arm.com        LSQRequest* request() { return _request; }
1137404SAli.Saidi@ARM.com        virtual void complete() = 0;
1147404SAli.Saidi@ARM.com        void writebackDone() { _request->writebackDone(); }
1157404SAli.Saidi@ARM.com    };
1167404SAli.Saidi@ARM.com
1177404SAli.Saidi@ARM.com    /** Memory operation metadata.
1187608SGene.Wu@arm.com     * This class holds the information about a memory operation. It lives
1197404SAli.Saidi@ARM.com     * from initiateAcc to resource deallocation at commit or squash.
1207404SAli.Saidi@ARM.com     * LSQRequest objects are owned by the LQ/SQ Entry in the LSQUnit that
1217404SAli.Saidi@ARM.com     * holds the operation. It is also used by the LSQSenderState. In addition,
1227404SAli.Saidi@ARM.com     * the LSQRequest is a TranslationState, therefore, upon squash, there must
1237404SAli.Saidi@ARM.com     * be a defined ownership transferal in case the LSQ resources are
1247608SGene.Wu@arm.com     * deallocated before the TLB is done using the TranslationState. If that
1257404SAli.Saidi@ARM.com     * happens, the LSQRequest will be self-owned, and responsible to detect
1267404SAli.Saidi@ARM.com     * that its services are no longer required and self-destruct.
1277404SAli.Saidi@ARM.com     *
1287404SAli.Saidi@ARM.com     * Lifetime of a LSQRequest:
1297404SAli.Saidi@ARM.com     *                 +--------------------+
1307946SGiacomo.Gabrielli@arm.com     *                 |LSQ creates and owns|
1317404SAli.Saidi@ARM.com     *                 +--------------------+
1327404SAli.Saidi@ARM.com     *                           |
1337404SAli.Saidi@ARM.com     *                 +--------------------+
1347404SAli.Saidi@ARM.com     *                 | Initate translation|
1357404SAli.Saidi@ARM.com     *                 +--------------------+
1367946SGiacomo.Gabrielli@arm.com     *                           |
1377404SAli.Saidi@ARM.com     *                        ___^___
1387404SAli.Saidi@ARM.com     *                    ___/       \___
1397404SAli.Saidi@ARM.com     *             ______/   Squashed?   \
1407404SAli.Saidi@ARM.com     *            |      \___         ___/
1417404SAli.Saidi@ARM.com     *            |          \___ ___/
1427946SGiacomo.Gabrielli@arm.com     *            |              v
1437404SAli.Saidi@ARM.com     *            |              |
1447404SAli.Saidi@ARM.com     *            |    +--------------------+
1457436Sdam.sunwoo@arm.com     *            |    |  Translation done  |
1467436Sdam.sunwoo@arm.com     *            |    +--------------------+
1477436Sdam.sunwoo@arm.com     *            |              |
1487436Sdam.sunwoo@arm.com     *            |    +--------------------+
1497436Sdam.sunwoo@arm.com     *            |    |     Send packet    |<------+
1507404SAli.Saidi@ARM.com     *            |    +--------------------+       |
1517404SAli.Saidi@ARM.com     *            |              |                  |
1527946SGiacomo.Gabrielli@arm.com     *            |           ___^___               |
1537404SAli.Saidi@ARM.com     *            |       ___/       \___           |
1547404SAli.Saidi@ARM.com     *            |  ____/   Squashed?   \          |
1557436Sdam.sunwoo@arm.com     *            | |    \___         ___/          |
1567436Sdam.sunwoo@arm.com     *            | |        \___ ___/              |
1577436Sdam.sunwoo@arm.com     *            | |            v                  |
1587436Sdam.sunwoo@arm.com     *            | |            |                  |
1597436Sdam.sunwoo@arm.com     *            | |         ___^___               |
1607436Sdam.sunwoo@arm.com     *            | |     ___/       \___           |
1617436Sdam.sunwoo@arm.com     *            | |    /     Done?     \__________|
1627436Sdam.sunwoo@arm.com     *            | |    \___         ___/
1637436Sdam.sunwoo@arm.com     *            | |        \___ ___/
1647436Sdam.sunwoo@arm.com     *            | |            v
1657436Sdam.sunwoo@arm.com     *            | |            |
1667436Sdam.sunwoo@arm.com     *            | |  +--------------------+
1677436Sdam.sunwoo@arm.com     *            | |  |    Manage stuff    |
1687436Sdam.sunwoo@arm.com     *            | |  |   Free resources   |
1697436Sdam.sunwoo@arm.com     *            | |  +--------------------+
1707436Sdam.sunwoo@arm.com     *            | |
1717436Sdam.sunwoo@arm.com     *            | |  +--------------------+
1727436Sdam.sunwoo@arm.com     *            | |  |  senderState owns  |
1737436Sdam.sunwoo@arm.com     *            | +->|  onRecvTimingResp  |
1747436Sdam.sunwoo@arm.com     *            |    |   free resources   |
1757404SAli.Saidi@ARM.com     *            |    +--------------------+
1767404SAli.Saidi@ARM.com     *            |
1777404SAli.Saidi@ARM.com     *            |   +----------------------+
1787404SAli.Saidi@ARM.com     *            |   |  self owned (Trans)  |
1797404SAli.Saidi@ARM.com     *            +-->| on TranslationFinish |
1807436Sdam.sunwoo@arm.com     *                |    free resources    |
1817404SAli.Saidi@ARM.com     *                +----------------------+
1827404SAli.Saidi@ARM.com     *
1837436Sdam.sunwoo@arm.com     *
1847436Sdam.sunwoo@arm.com     */
1857436Sdam.sunwoo@arm.com    class LSQRequest : public BaseTLB::Translation
1867436Sdam.sunwoo@arm.com    {
1877404SAli.Saidi@ARM.com      protected:
1887404SAli.Saidi@ARM.com        typedef uint32_t FlagsStorage;
1897404SAli.Saidi@ARM.com        typedef ::Flags<FlagsStorage> FlagsType;
1907946SGiacomo.Gabrielli@arm.com
1917404SAli.Saidi@ARM.com        enum Flag : FlagsStorage
1927404SAli.Saidi@ARM.com        {
1937404SAli.Saidi@ARM.com            IsLoad              = 0x00000001,
1947404SAli.Saidi@ARM.com            /** True if this is a store/atomic that writes registers (SC). */
1957404SAli.Saidi@ARM.com            WbStore             = 0x00000002,
1967404SAli.Saidi@ARM.com            Delayed             = 0x00000004,
1977404SAli.Saidi@ARM.com            IsSplit             = 0x00000008,
1987404SAli.Saidi@ARM.com            /** True if any translation has been sent to TLB. */
1997404SAli.Saidi@ARM.com            TranslationStarted  = 0x00000010,
2007404SAli.Saidi@ARM.com            /** True if there are un-replied outbound translations.. */
2017404SAli.Saidi@ARM.com            TranslationFinished = 0x00000020,
2027404SAli.Saidi@ARM.com            Sent                = 0x00000040,
2037404SAli.Saidi@ARM.com            Retry               = 0x00000080,
2047404SAli.Saidi@ARM.com            Complete            = 0x00000100,
2057404SAli.Saidi@ARM.com            /** Ownership tracking flags. */
2067404SAli.Saidi@ARM.com            /** Translation squashed. */
2077404SAli.Saidi@ARM.com            TranslationSquashed = 0x00000200,
2087404SAli.Saidi@ARM.com            /** Request discarded */
2097404SAli.Saidi@ARM.com            Discarded           = 0x00000400,
2107404SAli.Saidi@ARM.com            /** LSQ resources freed. */
2117404SAli.Saidi@ARM.com            LSQEntryFreed       = 0x00000800,
2127404SAli.Saidi@ARM.com            /** Store written back. */
2137404SAli.Saidi@ARM.com            WritebackScheduled  = 0x00001000,
2147404SAli.Saidi@ARM.com            WritebackDone       = 0x00002000,
2157404SAli.Saidi@ARM.com            /** True if this is an atomic request */
2167404SAli.Saidi@ARM.com            IsAtomic            = 0x00004000
2177404SAli.Saidi@ARM.com        };
2187404SAli.Saidi@ARM.com        FlagsType flags;
2197404SAli.Saidi@ARM.com
2207404SAli.Saidi@ARM.com        enum class State
2217946SGiacomo.Gabrielli@arm.com        {
2227946SGiacomo.Gabrielli@arm.com            NotIssued,
2237404SAli.Saidi@ARM.com            Translation,
2247404SAli.Saidi@ARM.com            Request,
2257404SAli.Saidi@ARM.com            Complete,
2267404SAli.Saidi@ARM.com            Squashed,
2277404SAli.Saidi@ARM.com            Fault,
2287404SAli.Saidi@ARM.com        };
2297404SAli.Saidi@ARM.com        State _state;
2307404SAli.Saidi@ARM.com        LSQSenderState* _senderState;
2317694SAli.Saidi@ARM.com        void setState(const State& newState) { _state = newState; }
2327694SAli.Saidi@ARM.com
2337694SAli.Saidi@ARM.com        uint32_t numTranslatedFragments;
2347694SAli.Saidi@ARM.com        uint32_t numInTranslationFragments;
2357694SAli.Saidi@ARM.com
2367694SAli.Saidi@ARM.com        /** LQ/SQ entry idx. */
2377694SAli.Saidi@ARM.com        uint32_t _entryIdx;
2387694SAli.Saidi@ARM.com
2397694SAli.Saidi@ARM.com        void markDelayed() override { flags.set(Flag::Delayed); }
2407436Sdam.sunwoo@arm.com        bool isDelayed() { return flags.isSet(Flag::Delayed); }
2417436Sdam.sunwoo@arm.com
2427436Sdam.sunwoo@arm.com      public:
2437436Sdam.sunwoo@arm.com        LSQUnit& _port;
2447436Sdam.sunwoo@arm.com        const DynInstPtr _inst;
2457436Sdam.sunwoo@arm.com        uint32_t _taskId;
2467436Sdam.sunwoo@arm.com        PacketDataPtr _data;
2477436Sdam.sunwoo@arm.com        std::vector<PacketPtr> _packets;
2487436Sdam.sunwoo@arm.com        std::vector<RequestPtr> _requests;
2497436Sdam.sunwoo@arm.com        std::vector<Fault> _fault;
2507436Sdam.sunwoo@arm.com        uint64_t* _res;
2517436Sdam.sunwoo@arm.com        const Addr _addr;
2527436Sdam.sunwoo@arm.com        const uint32_t _size;
2537436Sdam.sunwoo@arm.com        const Request::Flags _flags;
2547436Sdam.sunwoo@arm.com        uint32_t _numOutstandingPackets;
2557436Sdam.sunwoo@arm.com        AtomicOpFunctor *_amo_op;
2567436Sdam.sunwoo@arm.com      protected:
2577436Sdam.sunwoo@arm.com        LSQUnit* lsqUnit() { return &_port; }
2587436Sdam.sunwoo@arm.com        LSQRequest(LSQUnit* port, const DynInstPtr& inst, bool isLoad) :
2597436Sdam.sunwoo@arm.com            _state(State::NotIssued), _senderState(nullptr),
2607436Sdam.sunwoo@arm.com            _port(*port), _inst(inst), _data(nullptr),
2617404SAli.Saidi@ARM.com            _res(nullptr), _addr(0), _size(0), _flags(0),
2627404SAli.Saidi@ARM.com            _numOutstandingPackets(0), _amo_op(nullptr)
2637439Sdam.sunwoo@arm.com        {
2647439Sdam.sunwoo@arm.com            flags.set(Flag::IsLoad, isLoad);
2657439Sdam.sunwoo@arm.com            flags.set(Flag::WbStore,
2667439Sdam.sunwoo@arm.com                      _inst->isStoreConditional() || _inst->isAtomic());
2677439Sdam.sunwoo@arm.com            flags.set(Flag::IsAtomic, _inst->isAtomic());
2687439Sdam.sunwoo@arm.com            install();
2697439Sdam.sunwoo@arm.com        }
2707439Sdam.sunwoo@arm.com        LSQRequest(LSQUnit* port, const DynInstPtr& inst, bool isLoad,
2717439Sdam.sunwoo@arm.com                   const Addr& addr, const uint32_t& size,
2727439Sdam.sunwoo@arm.com                   const Request::Flags& flags_,
2737439Sdam.sunwoo@arm.com                   PacketDataPtr data = nullptr, uint64_t* res = nullptr,
2747439Sdam.sunwoo@arm.com                   AtomicOpFunctor* amo_op = nullptr)
2757439Sdam.sunwoo@arm.com            : _state(State::NotIssued), _senderState(nullptr),
2767439Sdam.sunwoo@arm.com            numTranslatedFragments(0),
2777439Sdam.sunwoo@arm.com            numInTranslationFragments(0),
2787439Sdam.sunwoo@arm.com            _port(*port), _inst(inst), _data(data),
2797439Sdam.sunwoo@arm.com            _res(res), _addr(addr), _size(size),
2807439Sdam.sunwoo@arm.com            _flags(flags_),
2817439Sdam.sunwoo@arm.com            _numOutstandingPackets(0),
2827439Sdam.sunwoo@arm.com            _amo_op(amo_op)
2837439Sdam.sunwoo@arm.com        {
2847439Sdam.sunwoo@arm.com            flags.set(Flag::IsLoad, isLoad);
2857439Sdam.sunwoo@arm.com            flags.set(Flag::WbStore,
2867439Sdam.sunwoo@arm.com                      _inst->isStoreConditional() || _inst->isAtomic());
2877439Sdam.sunwoo@arm.com            flags.set(Flag::IsAtomic, _inst->isAtomic());
2887439Sdam.sunwoo@arm.com            install();
2897439Sdam.sunwoo@arm.com        }
2907439Sdam.sunwoo@arm.com
2917439Sdam.sunwoo@arm.com        bool
2927439Sdam.sunwoo@arm.com        isLoad() const
2937439Sdam.sunwoo@arm.com        {
2947439Sdam.sunwoo@arm.com            return flags.isSet(Flag::IsLoad);
2957439Sdam.sunwoo@arm.com        }
2967439Sdam.sunwoo@arm.com
2977439Sdam.sunwoo@arm.com        bool
2988733Sgeoffrey.blake@arm.com        isAtomic() const
2998733Sgeoffrey.blake@arm.com        {
3008733Sgeoffrey.blake@arm.com            return flags.isSet(Flag::IsAtomic);
3017439Sdam.sunwoo@arm.com        }
3027439Sdam.sunwoo@arm.com
3037439Sdam.sunwoo@arm.com        /** Install the request in the LQ/SQ. */
3047439Sdam.sunwoo@arm.com        void install()
3057439Sdam.sunwoo@arm.com        {
3067439Sdam.sunwoo@arm.com            if (isLoad()) {
3077439Sdam.sunwoo@arm.com                _port.loadQueue[_inst->lqIdx].setRequest(this);
3087439Sdam.sunwoo@arm.com            } else {
3097439Sdam.sunwoo@arm.com                // Store, StoreConditional, and Atomic requests are pushed
3107439Sdam.sunwoo@arm.com                // to this storeQueue
3117439Sdam.sunwoo@arm.com                _port.storeQueue[_inst->sqIdx].setRequest(this);
3127439Sdam.sunwoo@arm.com            }
3137439Sdam.sunwoo@arm.com        }
3147439Sdam.sunwoo@arm.com        virtual bool
3157439Sdam.sunwoo@arm.com        squashed() const override
3167439Sdam.sunwoo@arm.com        {
3177439Sdam.sunwoo@arm.com            return _inst->isSquashed();
3187439Sdam.sunwoo@arm.com        }
3197653Sgene.wu@arm.com
3207653Sgene.wu@arm.com        /**
3217653Sgene.wu@arm.com         * Test if the LSQRequest has been released, i.e. self-owned.
3227653Sgene.wu@arm.com         * An LSQRequest manages itself when the resources on the LSQ are freed
3237653Sgene.wu@arm.com         * but the translation is still going on and the LSQEntry was freed.
3247653Sgene.wu@arm.com         */
3257439Sdam.sunwoo@arm.com        bool
3267728SAli.Saidi@ARM.com        isReleased()
3277728SAli.Saidi@ARM.com        {
3288902Sandreas.hansson@arm.com            return flags.isSet(Flag::LSQEntryFreed) ||
3297728SAli.Saidi@ARM.com                flags.isSet(Flag::Discarded);
3307728SAli.Saidi@ARM.com        }
3317404SAli.Saidi@ARM.com
3328851Sandreas.hansson@arm.com        /** Release the LSQRequest.
3337404SAli.Saidi@ARM.com         * Notify the sender state that the request it points to is not valid
3347404SAli.Saidi@ARM.com         * anymore. Understand if the request is orphan (self-managed) and if
3357404SAli.Saidi@ARM.com         * so, mark it as freed, else destroy it, as this means
3367404SAli.Saidi@ARM.com         * the end of its life cycle.
3377404SAli.Saidi@ARM.com         * An LSQRequest is orphan when its resources are released
3387404SAli.Saidi@ARM.com         * but there is any in-flight translation request to the TLB or access
3397404SAli.Saidi@ARM.com         * request to the memory.
3407439Sdam.sunwoo@arm.com         */
3417437Sdam.sunwoo@arm.com        void release(Flag reason)
3427728SAli.Saidi@ARM.com        {
3437728SAli.Saidi@ARM.com            assert(reason == Flag::LSQEntryFreed || reason == Flag::Discarded);
3447728SAli.Saidi@ARM.com            if (!isAnyOutstandingRequest()) {
3458832SAli.Saidi@ARM.com                delete this;
3468832SAli.Saidi@ARM.com            } else {
3478832SAli.Saidi@ARM.com                if (_senderState) {
3487404SAli.Saidi@ARM.com                    _senderState->deleteRequest();
3497404SAli.Saidi@ARM.com                }
3507404SAli.Saidi@ARM.com                flags.set(reason);
3517404SAli.Saidi@ARM.com            }
3527404SAli.Saidi@ARM.com        }
3537404SAli.Saidi@ARM.com
3547404SAli.Saidi@ARM.com        /** Destructor.
3557404SAli.Saidi@ARM.com         * The LSQRequest owns the request. If the packet has already been
3567404SAli.Saidi@ARM.com         * sent, the sender state will be deleted upon receiving the reply.
3577404SAli.Saidi@ARM.com         */
3587404SAli.Saidi@ARM.com        virtual ~LSQRequest()
3597733SAli.Saidi@ARM.com        {
3607748SAli.Saidi@ARM.com            assert(!isAnyOutstandingRequest());
3617404SAli.Saidi@ARM.com            _inst->savedReq = nullptr;
3627404SAli.Saidi@ARM.com            if (_senderState)
3637404SAli.Saidi@ARM.com                delete _senderState;
3648733Sgeoffrey.blake@arm.com
3657404SAli.Saidi@ARM.com            for (auto r: _packets)
3667404SAli.Saidi@ARM.com                delete r;
3677439Sdam.sunwoo@arm.com        };
3687439Sdam.sunwoo@arm.com
3697404SAli.Saidi@ARM.com
3707404SAli.Saidi@ARM.com      public:
3717404SAli.Saidi@ARM.com        /** Convenience getters/setters. */
3727404SAli.Saidi@ARM.com        /** @{ */
3737437Sdam.sunwoo@arm.com        /** Set up Context numbers. */
3747437Sdam.sunwoo@arm.com        void
3757404SAli.Saidi@ARM.com        setContext(const ContextID& context_id)
3767404SAli.Saidi@ARM.com        {
3777437Sdam.sunwoo@arm.com            request()->setContext(context_id);
3787437Sdam.sunwoo@arm.com        }
3797404SAli.Saidi@ARM.com
3807728SAli.Saidi@ARM.com        const DynInstPtr&
3817728SAli.Saidi@ARM.com        instruction()
3827728SAli.Saidi@ARM.com        {
3837404SAli.Saidi@ARM.com            return _inst;
3847728SAli.Saidi@ARM.com        }
3857404SAli.Saidi@ARM.com
3867404SAli.Saidi@ARM.com        /** Set up virtual request.
3877404SAli.Saidi@ARM.com         * For a previously allocated Request objects.
3887404SAli.Saidi@ARM.com         */
3897404SAli.Saidi@ARM.com        void
3907404SAli.Saidi@ARM.com        setVirt(int asid, Addr vaddr, unsigned size, Request::Flags flags_,
3917404SAli.Saidi@ARM.com                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
1029template <class Impl>
1030Fault
1031LSQ<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
1038template <class Impl>
1039Fault
1040LSQ<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__
1048