12292SN/A/*
213590Srekai.gonzalezalberquilla@arm.com * Copyright (c) 2011-2012, 2014, 2018 ARM Limited
310239Sbinhpham@cs.rutgers.edu * Copyright (c) 2013 Advanced Micro Devices, Inc.
48707Sandreas.hansson@arm.com * All rights reserved
58707Sandreas.hansson@arm.com *
68707Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
78707Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual
88707Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
98707Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
108707Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
118707Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
128707Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
138707Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
148707Sandreas.hansson@arm.com *
152329SN/A * Copyright (c) 2004-2006 The Regents of The University of Michigan
162292SN/A * All rights reserved.
172292SN/A *
182292SN/A * Redistribution and use in source and binary forms, with or without
192292SN/A * modification, are permitted provided that the following conditions are
202292SN/A * met: redistributions of source code must retain the above copyright
212292SN/A * notice, this list of conditions and the following disclaimer;
222292SN/A * redistributions in binary form must reproduce the above copyright
232292SN/A * notice, this list of conditions and the following disclaimer in the
242292SN/A * documentation and/or other materials provided with the distribution;
252292SN/A * neither the name of the copyright holders nor the names of its
262292SN/A * contributors may be used to endorse or promote products derived from
272292SN/A * this software without specific prior written permission.
282292SN/A *
292292SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
302292SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
312292SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
322292SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
332292SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
342292SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
352292SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
362292SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
372292SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
382292SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
392292SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
402689Sktlim@umich.edu *
412689Sktlim@umich.edu * Authors: Korey Sewell
422292SN/A */
432292SN/A
442292SN/A#ifndef __CPU_O3_LSQ_HH__
452292SN/A#define __CPU_O3_LSQ_HH__
462292SN/A
472292SN/A#include <map>
482292SN/A#include <queue>
492292SN/A
5013590Srekai.gonzalezalberquilla@arm.com#include "arch/generic/tlb.hh"
5113590Srekai.gonzalezalberquilla@arm.com#include "cpu/inst_seq.hh"
528229Snate@binkert.org#include "cpu/o3/lsq_unit.hh"
5313954Sgiacomo.gabrielli@arm.com#include "cpu/utils.hh"
5413560Snikos.nikoleris@arm.com#include "enums/SMTQueuePolicy.hh"
552669Sktlim@umich.edu#include "mem/port.hh"
562292SN/A#include "sim/sim_object.hh"
572292SN/A
588737Skoansin.tan@gmail.comstruct DerivO3CPUParams;
595529Snate@binkert.org
602292SN/Atemplate <class Impl>
6114194Sgabeblack@google.comclass FullO3CPU;
6214194Sgabeblack@google.com
6314194Sgabeblack@google.comtemplate <class Impl>
6413590Srekai.gonzalezalberquilla@arm.comclass LSQ
6513590Srekai.gonzalezalberquilla@arm.com
6613590Srekai.gonzalezalberquilla@arm.com{
672292SN/A  public:
682733Sktlim@umich.edu    typedef typename Impl::O3CPU O3CPU;
692292SN/A    typedef typename Impl::DynInstPtr DynInstPtr;
702292SN/A    typedef typename Impl::CPUPol::IEW IEW;
712292SN/A    typedef typename Impl::CPUPol::LSQUnit LSQUnit;
722292SN/A
7313590Srekai.gonzalezalberquilla@arm.com    class LSQRequest;
7413590Srekai.gonzalezalberquilla@arm.com    /** Derived class to hold any sender state the LSQ needs. */
7513590Srekai.gonzalezalberquilla@arm.com    class LSQSenderState : public Packet::SenderState
7613590Srekai.gonzalezalberquilla@arm.com    {
7713590Srekai.gonzalezalberquilla@arm.com      protected:
7813590Srekai.gonzalezalberquilla@arm.com        /** The senderState needs to know the LSQRequest who owns it. */
7913590Srekai.gonzalezalberquilla@arm.com        LSQRequest* _request;
8013590Srekai.gonzalezalberquilla@arm.com
8113590Srekai.gonzalezalberquilla@arm.com        /** Default constructor. */
8213590Srekai.gonzalezalberquilla@arm.com        LSQSenderState(LSQRequest* request, bool isLoad_)
8313590Srekai.gonzalezalberquilla@arm.com            : _request(request), mainPkt(nullptr), pendingPacket(nullptr),
8413590Srekai.gonzalezalberquilla@arm.com              outstanding(0), isLoad(isLoad_), needWB(isLoad_), isSplit(false),
8513590Srekai.gonzalezalberquilla@arm.com              pktToSend(false), deleted(false)
8613590Srekai.gonzalezalberquilla@arm.com          { }
8713590Srekai.gonzalezalberquilla@arm.com      public:
8813590Srekai.gonzalezalberquilla@arm.com
8913590Srekai.gonzalezalberquilla@arm.com        /** Instruction which initiated the access to memory. */
9013590Srekai.gonzalezalberquilla@arm.com        DynInstPtr inst;
9113590Srekai.gonzalezalberquilla@arm.com        /** The main packet from a split load, used during writeback. */
9213590Srekai.gonzalezalberquilla@arm.com        PacketPtr mainPkt;
9313590Srekai.gonzalezalberquilla@arm.com        /** A second packet from a split store that needs sending. */
9413590Srekai.gonzalezalberquilla@arm.com        PacketPtr pendingPacket;
9513590Srekai.gonzalezalberquilla@arm.com        /** Number of outstanding packets to complete. */
9613590Srekai.gonzalezalberquilla@arm.com        uint8_t outstanding;
9713590Srekai.gonzalezalberquilla@arm.com        /** Whether or not it is a load. */
9813590Srekai.gonzalezalberquilla@arm.com        bool isLoad;
9913590Srekai.gonzalezalberquilla@arm.com        /** Whether or not the instruction will need to writeback. */
10013590Srekai.gonzalezalberquilla@arm.com        bool needWB;
10113590Srekai.gonzalezalberquilla@arm.com        /** Whether or not this access is split in two. */
10213590Srekai.gonzalezalberquilla@arm.com        bool isSplit;
10313590Srekai.gonzalezalberquilla@arm.com        /** Whether or not there is a packet that needs sending. */
10413590Srekai.gonzalezalberquilla@arm.com        bool pktToSend;
10513590Srekai.gonzalezalberquilla@arm.com        /** Has the request been deleted?
10613590Srekai.gonzalezalberquilla@arm.com         * LSQ entries can be squashed before the response comes back. in that
10713590Srekai.gonzalezalberquilla@arm.com         * case the SenderState knows.
10813590Srekai.gonzalezalberquilla@arm.com         */
10913590Srekai.gonzalezalberquilla@arm.com        bool deleted;
11013590Srekai.gonzalezalberquilla@arm.com        ContextID contextId() { return inst->contextId(); }
11113590Srekai.gonzalezalberquilla@arm.com
11213590Srekai.gonzalezalberquilla@arm.com        /** Completes a packet and returns whether the access is finished. */
11313590Srekai.gonzalezalberquilla@arm.com        inline bool isComplete() { return outstanding == 0; }
11413590Srekai.gonzalezalberquilla@arm.com        inline void deleteRequest() { deleted = true; }
11513590Srekai.gonzalezalberquilla@arm.com        inline bool alive() { return !deleted; }
11613590Srekai.gonzalezalberquilla@arm.com        LSQRequest* request() { return _request; }
11713590Srekai.gonzalezalberquilla@arm.com        virtual void complete() = 0;
11813590Srekai.gonzalezalberquilla@arm.com        void writebackDone() { _request->writebackDone(); }
11913590Srekai.gonzalezalberquilla@arm.com    };
12013590Srekai.gonzalezalberquilla@arm.com
12114194Sgabeblack@google.com    /**
12214194Sgabeblack@google.com     * DcachePort class for the load/store queue.
12314194Sgabeblack@google.com     */
12414194Sgabeblack@google.com    class DcachePort : public MasterPort
12514194Sgabeblack@google.com    {
12614194Sgabeblack@google.com      protected:
12714194Sgabeblack@google.com
12814194Sgabeblack@google.com        /** Pointer to LSQ. */
12914194Sgabeblack@google.com        LSQ<Impl> *lsq;
13014194Sgabeblack@google.com        FullO3CPU<Impl> *cpu;
13114194Sgabeblack@google.com
13214194Sgabeblack@google.com      public:
13314194Sgabeblack@google.com        /** Default constructor. */
13414194Sgabeblack@google.com        DcachePort(LSQ<Impl> *_lsq, FullO3CPU<Impl>* _cpu)
13514194Sgabeblack@google.com            : MasterPort(_cpu->name() + ".dcache_port", _cpu), lsq(_lsq),
13614194Sgabeblack@google.com              cpu(_cpu)
13714194Sgabeblack@google.com        { }
13814194Sgabeblack@google.com
13914194Sgabeblack@google.com      protected:
14014194Sgabeblack@google.com
14114194Sgabeblack@google.com        /** Timing version of receive.  Handles writing back and
14214194Sgabeblack@google.com         * completing the load or store that has returned from
14314194Sgabeblack@google.com         * memory. */
14414194Sgabeblack@google.com        virtual bool recvTimingResp(PacketPtr pkt);
14514194Sgabeblack@google.com        virtual void recvTimingSnoopReq(PacketPtr pkt);
14614194Sgabeblack@google.com
14714194Sgabeblack@google.com        virtual void recvFunctionalSnoop(PacketPtr pkt)
14814194Sgabeblack@google.com        {
14914194Sgabeblack@google.com            // @todo: Is there a need for potential invalidation here?
15014194Sgabeblack@google.com        }
15114194Sgabeblack@google.com
15214194Sgabeblack@google.com        /** Handles doing a retry of the previous send. */
15314194Sgabeblack@google.com        virtual void recvReqRetry();
15414194Sgabeblack@google.com
15514194Sgabeblack@google.com        /**
15614194Sgabeblack@google.com         * As this CPU requires snooping to maintain the load store queue
15714194Sgabeblack@google.com         * change the behaviour from the base CPU port.
15814194Sgabeblack@google.com         *
15914194Sgabeblack@google.com         * @return true since we have to snoop
16014194Sgabeblack@google.com         */
16114194Sgabeblack@google.com        virtual bool isSnooping() const { return true; }
16214194Sgabeblack@google.com    };
16314194Sgabeblack@google.com
16413590Srekai.gonzalezalberquilla@arm.com    /** Memory operation metadata.
16513590Srekai.gonzalezalberquilla@arm.com     * This class holds the information about a memory operation. It lives
16613590Srekai.gonzalezalberquilla@arm.com     * from initiateAcc to resource deallocation at commit or squash.
16713590Srekai.gonzalezalberquilla@arm.com     * LSQRequest objects are owned by the LQ/SQ Entry in the LSQUnit that
16813590Srekai.gonzalezalberquilla@arm.com     * holds the operation. It is also used by the LSQSenderState. In addition,
16913590Srekai.gonzalezalberquilla@arm.com     * the LSQRequest is a TranslationState, therefore, upon squash, there must
17013590Srekai.gonzalezalberquilla@arm.com     * be a defined ownership transferal in case the LSQ resources are
17113590Srekai.gonzalezalberquilla@arm.com     * deallocated before the TLB is done using the TranslationState. If that
17213590Srekai.gonzalezalberquilla@arm.com     * happens, the LSQRequest will be self-owned, and responsible to detect
17313590Srekai.gonzalezalberquilla@arm.com     * that its services are no longer required and self-destruct.
17413590Srekai.gonzalezalberquilla@arm.com     *
17513590Srekai.gonzalezalberquilla@arm.com     * Lifetime of a LSQRequest:
17613590Srekai.gonzalezalberquilla@arm.com     *                 +--------------------+
17713590Srekai.gonzalezalberquilla@arm.com     *                 |LSQ creates and owns|
17813590Srekai.gonzalezalberquilla@arm.com     *                 +--------------------+
17913590Srekai.gonzalezalberquilla@arm.com     *                           |
18013590Srekai.gonzalezalberquilla@arm.com     *                 +--------------------+
18113590Srekai.gonzalezalberquilla@arm.com     *                 | Initate translation|
18213590Srekai.gonzalezalberquilla@arm.com     *                 +--------------------+
18313590Srekai.gonzalezalberquilla@arm.com     *                           |
18413590Srekai.gonzalezalberquilla@arm.com     *                        ___^___
18513590Srekai.gonzalezalberquilla@arm.com     *                    ___/       \___
18613590Srekai.gonzalezalberquilla@arm.com     *             ______/   Squashed?   \
18713590Srekai.gonzalezalberquilla@arm.com     *            |      \___         ___/
18813590Srekai.gonzalezalberquilla@arm.com     *            |          \___ ___/
18913590Srekai.gonzalezalberquilla@arm.com     *            |              v
19013590Srekai.gonzalezalberquilla@arm.com     *            |              |
19113590Srekai.gonzalezalberquilla@arm.com     *            |    +--------------------+
19213590Srekai.gonzalezalberquilla@arm.com     *            |    |  Translation done  |
19313590Srekai.gonzalezalberquilla@arm.com     *            |    +--------------------+
19413590Srekai.gonzalezalberquilla@arm.com     *            |              |
19513590Srekai.gonzalezalberquilla@arm.com     *            |    +--------------------+
19613590Srekai.gonzalezalberquilla@arm.com     *            |    |     Send packet    |<------+
19713590Srekai.gonzalezalberquilla@arm.com     *            |    +--------------------+       |
19813590Srekai.gonzalezalberquilla@arm.com     *            |              |                  |
19913590Srekai.gonzalezalberquilla@arm.com     *            |           ___^___               |
20013590Srekai.gonzalezalberquilla@arm.com     *            |       ___/       \___           |
20113590Srekai.gonzalezalberquilla@arm.com     *            |  ____/   Squashed?   \          |
20213590Srekai.gonzalezalberquilla@arm.com     *            | |    \___         ___/          |
20313590Srekai.gonzalezalberquilla@arm.com     *            | |        \___ ___/              |
20413590Srekai.gonzalezalberquilla@arm.com     *            | |            v                  |
20513590Srekai.gonzalezalberquilla@arm.com     *            | |            |                  |
20613590Srekai.gonzalezalberquilla@arm.com     *            | |         ___^___               |
20713590Srekai.gonzalezalberquilla@arm.com     *            | |     ___/       \___           |
20813590Srekai.gonzalezalberquilla@arm.com     *            | |    /     Done?     \__________|
20913590Srekai.gonzalezalberquilla@arm.com     *            | |    \___         ___/
21013590Srekai.gonzalezalberquilla@arm.com     *            | |        \___ ___/
21113590Srekai.gonzalezalberquilla@arm.com     *            | |            v
21213590Srekai.gonzalezalberquilla@arm.com     *            | |            |
21313590Srekai.gonzalezalberquilla@arm.com     *            | |  +--------------------+
21413590Srekai.gonzalezalberquilla@arm.com     *            | |  |    Manage stuff    |
21513590Srekai.gonzalezalberquilla@arm.com     *            | |  |   Free resources   |
21613590Srekai.gonzalezalberquilla@arm.com     *            | |  +--------------------+
21713590Srekai.gonzalezalberquilla@arm.com     *            | |
21813590Srekai.gonzalezalberquilla@arm.com     *            | |  +--------------------+
21913590Srekai.gonzalezalberquilla@arm.com     *            | |  |  senderState owns  |
22013590Srekai.gonzalezalberquilla@arm.com     *            | +->|  onRecvTimingResp  |
22113590Srekai.gonzalezalberquilla@arm.com     *            |    |   free resources   |
22213590Srekai.gonzalezalberquilla@arm.com     *            |    +--------------------+
22313590Srekai.gonzalezalberquilla@arm.com     *            |
22413590Srekai.gonzalezalberquilla@arm.com     *            |   +----------------------+
22513590Srekai.gonzalezalberquilla@arm.com     *            |   |  self owned (Trans)  |
22613590Srekai.gonzalezalberquilla@arm.com     *            +-->| on TranslationFinish |
22713590Srekai.gonzalezalberquilla@arm.com     *                |    free resources    |
22813590Srekai.gonzalezalberquilla@arm.com     *                +----------------------+
22913590Srekai.gonzalezalberquilla@arm.com     *
23013590Srekai.gonzalezalberquilla@arm.com     *
23113590Srekai.gonzalezalberquilla@arm.com     */
23213590Srekai.gonzalezalberquilla@arm.com    class LSQRequest : public BaseTLB::Translation
23313590Srekai.gonzalezalberquilla@arm.com    {
23413590Srekai.gonzalezalberquilla@arm.com      protected:
23513590Srekai.gonzalezalberquilla@arm.com        typedef uint32_t FlagsStorage;
23613590Srekai.gonzalezalberquilla@arm.com        typedef ::Flags<FlagsStorage> FlagsType;
23713590Srekai.gonzalezalberquilla@arm.com
23813590Srekai.gonzalezalberquilla@arm.com        enum Flag : FlagsStorage
23913590Srekai.gonzalezalberquilla@arm.com        {
24013590Srekai.gonzalezalberquilla@arm.com            IsLoad              = 0x00000001,
24113652Sqtt2@cornell.edu            /** True if this is a store/atomic that writes registers (SC). */
24213590Srekai.gonzalezalberquilla@arm.com            WbStore             = 0x00000002,
24313590Srekai.gonzalezalberquilla@arm.com            Delayed             = 0x00000004,
24413590Srekai.gonzalezalberquilla@arm.com            IsSplit             = 0x00000008,
24513590Srekai.gonzalezalberquilla@arm.com            /** True if any translation has been sent to TLB. */
24613590Srekai.gonzalezalberquilla@arm.com            TranslationStarted  = 0x00000010,
24713590Srekai.gonzalezalberquilla@arm.com            /** True if there are un-replied outbound translations.. */
24813590Srekai.gonzalezalberquilla@arm.com            TranslationFinished = 0x00000020,
24913590Srekai.gonzalezalberquilla@arm.com            Sent                = 0x00000040,
25013590Srekai.gonzalezalberquilla@arm.com            Retry               = 0x00000080,
25113590Srekai.gonzalezalberquilla@arm.com            Complete            = 0x00000100,
25213590Srekai.gonzalezalberquilla@arm.com            /** Ownership tracking flags. */
25313590Srekai.gonzalezalberquilla@arm.com            /** Translation squashed. */
25413590Srekai.gonzalezalberquilla@arm.com            TranslationSquashed = 0x00000200,
25513590Srekai.gonzalezalberquilla@arm.com            /** Request discarded */
25613590Srekai.gonzalezalberquilla@arm.com            Discarded           = 0x00000400,
25713590Srekai.gonzalezalberquilla@arm.com            /** LSQ resources freed. */
25813590Srekai.gonzalezalberquilla@arm.com            LSQEntryFreed       = 0x00000800,
25913590Srekai.gonzalezalberquilla@arm.com            /** Store written back. */
26013590Srekai.gonzalezalberquilla@arm.com            WritebackScheduled  = 0x00001000,
26113652Sqtt2@cornell.edu            WritebackDone       = 0x00002000,
26213652Sqtt2@cornell.edu            /** True if this is an atomic request */
26313652Sqtt2@cornell.edu            IsAtomic            = 0x00004000
26413590Srekai.gonzalezalberquilla@arm.com        };
26513590Srekai.gonzalezalberquilla@arm.com        FlagsType flags;
26613590Srekai.gonzalezalberquilla@arm.com
26713590Srekai.gonzalezalberquilla@arm.com        enum class State
26813590Srekai.gonzalezalberquilla@arm.com        {
26913590Srekai.gonzalezalberquilla@arm.com            NotIssued,
27013590Srekai.gonzalezalberquilla@arm.com            Translation,
27113590Srekai.gonzalezalberquilla@arm.com            Request,
27213590Srekai.gonzalezalberquilla@arm.com            Fault,
27314105Sgabor.dozsa@arm.com            PartialFault,
27413590Srekai.gonzalezalberquilla@arm.com        };
27513590Srekai.gonzalezalberquilla@arm.com        State _state;
27613590Srekai.gonzalezalberquilla@arm.com        LSQSenderState* _senderState;
27713590Srekai.gonzalezalberquilla@arm.com        void setState(const State& newState) { _state = newState; }
27813590Srekai.gonzalezalberquilla@arm.com
27913590Srekai.gonzalezalberquilla@arm.com        uint32_t numTranslatedFragments;
28013590Srekai.gonzalezalberquilla@arm.com        uint32_t numInTranslationFragments;
28113590Srekai.gonzalezalberquilla@arm.com
28213590Srekai.gonzalezalberquilla@arm.com        /** LQ/SQ entry idx. */
28313590Srekai.gonzalezalberquilla@arm.com        uint32_t _entryIdx;
28413590Srekai.gonzalezalberquilla@arm.com
28513628SAndrea.Mondelli@ucf.edu        void markDelayed() override { flags.set(Flag::Delayed); }
28613590Srekai.gonzalezalberquilla@arm.com        bool isDelayed() { return flags.isSet(Flag::Delayed); }
28713590Srekai.gonzalezalberquilla@arm.com
28813590Srekai.gonzalezalberquilla@arm.com      public:
28913590Srekai.gonzalezalberquilla@arm.com        LSQUnit& _port;
29013590Srekai.gonzalezalberquilla@arm.com        const DynInstPtr _inst;
29113590Srekai.gonzalezalberquilla@arm.com        uint32_t _taskId;
29213590Srekai.gonzalezalberquilla@arm.com        PacketDataPtr _data;
29313590Srekai.gonzalezalberquilla@arm.com        std::vector<PacketPtr> _packets;
29413590Srekai.gonzalezalberquilla@arm.com        std::vector<RequestPtr> _requests;
29513590Srekai.gonzalezalberquilla@arm.com        std::vector<Fault> _fault;
29613590Srekai.gonzalezalberquilla@arm.com        uint64_t* _res;
29713590Srekai.gonzalezalberquilla@arm.com        const Addr _addr;
29813590Srekai.gonzalezalberquilla@arm.com        const uint32_t _size;
29913590Srekai.gonzalezalberquilla@arm.com        const Request::Flags _flags;
30013954Sgiacomo.gabrielli@arm.com        std::vector<bool> _byteEnable;
30113590Srekai.gonzalezalberquilla@arm.com        uint32_t _numOutstandingPackets;
30214297Sjordi.vaquero@metempsy.com        AtomicOpFunctorPtr _amo_op;
30313590Srekai.gonzalezalberquilla@arm.com      protected:
30413590Srekai.gonzalezalberquilla@arm.com        LSQUnit* lsqUnit() { return &_port; }
30513590Srekai.gonzalezalberquilla@arm.com        LSQRequest(LSQUnit* port, const DynInstPtr& inst, bool isLoad) :
30613590Srekai.gonzalezalberquilla@arm.com            _state(State::NotIssued), _senderState(nullptr),
30713590Srekai.gonzalezalberquilla@arm.com            _port(*port), _inst(inst), _data(nullptr),
30813590Srekai.gonzalezalberquilla@arm.com            _res(nullptr), _addr(0), _size(0), _flags(0),
30913652Sqtt2@cornell.edu            _numOutstandingPackets(0), _amo_op(nullptr)
31013590Srekai.gonzalezalberquilla@arm.com        {
31113590Srekai.gonzalezalberquilla@arm.com            flags.set(Flag::IsLoad, isLoad);
31213652Sqtt2@cornell.edu            flags.set(Flag::WbStore,
31313652Sqtt2@cornell.edu                      _inst->isStoreConditional() || _inst->isAtomic());
31413652Sqtt2@cornell.edu            flags.set(Flag::IsAtomic, _inst->isAtomic());
31513590Srekai.gonzalezalberquilla@arm.com            install();
31613590Srekai.gonzalezalberquilla@arm.com        }
31713590Srekai.gonzalezalberquilla@arm.com        LSQRequest(LSQUnit* port, const DynInstPtr& inst, bool isLoad,
31813590Srekai.gonzalezalberquilla@arm.com                   const Addr& addr, const uint32_t& size,
31913590Srekai.gonzalezalberquilla@arm.com                   const Request::Flags& flags_,
32013652Sqtt2@cornell.edu                   PacketDataPtr data = nullptr, uint64_t* res = nullptr,
32114297Sjordi.vaquero@metempsy.com                   AtomicOpFunctorPtr amo_op = nullptr)
32213590Srekai.gonzalezalberquilla@arm.com            : _state(State::NotIssued), _senderState(nullptr),
32313590Srekai.gonzalezalberquilla@arm.com            numTranslatedFragments(0),
32413590Srekai.gonzalezalberquilla@arm.com            numInTranslationFragments(0),
32513590Srekai.gonzalezalberquilla@arm.com            _port(*port), _inst(inst), _data(data),
32613590Srekai.gonzalezalberquilla@arm.com            _res(res), _addr(addr), _size(size),
32713590Srekai.gonzalezalberquilla@arm.com            _flags(flags_),
32813652Sqtt2@cornell.edu            _numOutstandingPackets(0),
32914297Sjordi.vaquero@metempsy.com            _amo_op(std::move(amo_op))
33013590Srekai.gonzalezalberquilla@arm.com        {
33113590Srekai.gonzalezalberquilla@arm.com            flags.set(Flag::IsLoad, isLoad);
33213652Sqtt2@cornell.edu            flags.set(Flag::WbStore,
33313652Sqtt2@cornell.edu                      _inst->isStoreConditional() || _inst->isAtomic());
33413652Sqtt2@cornell.edu            flags.set(Flag::IsAtomic, _inst->isAtomic());
33513590Srekai.gonzalezalberquilla@arm.com            install();
33613590Srekai.gonzalezalberquilla@arm.com        }
33713590Srekai.gonzalezalberquilla@arm.com
33813590Srekai.gonzalezalberquilla@arm.com        bool
33913590Srekai.gonzalezalberquilla@arm.com        isLoad() const
34013590Srekai.gonzalezalberquilla@arm.com        {
34113590Srekai.gonzalezalberquilla@arm.com            return flags.isSet(Flag::IsLoad);
34213590Srekai.gonzalezalberquilla@arm.com        }
34313590Srekai.gonzalezalberquilla@arm.com
34413652Sqtt2@cornell.edu        bool
34513652Sqtt2@cornell.edu        isAtomic() const
34613652Sqtt2@cornell.edu        {
34713652Sqtt2@cornell.edu            return flags.isSet(Flag::IsAtomic);
34813652Sqtt2@cornell.edu        }
34913652Sqtt2@cornell.edu
35013590Srekai.gonzalezalberquilla@arm.com        /** Install the request in the LQ/SQ. */
35113590Srekai.gonzalezalberquilla@arm.com        void install()
35213590Srekai.gonzalezalberquilla@arm.com        {
35313590Srekai.gonzalezalberquilla@arm.com            if (isLoad()) {
35413590Srekai.gonzalezalberquilla@arm.com                _port.loadQueue[_inst->lqIdx].setRequest(this);
35513590Srekai.gonzalezalberquilla@arm.com            } else {
35613652Sqtt2@cornell.edu                // Store, StoreConditional, and Atomic requests are pushed
35713652Sqtt2@cornell.edu                // to this storeQueue
35813590Srekai.gonzalezalberquilla@arm.com                _port.storeQueue[_inst->sqIdx].setRequest(this);
35913590Srekai.gonzalezalberquilla@arm.com            }
36013590Srekai.gonzalezalberquilla@arm.com        }
36113590Srekai.gonzalezalberquilla@arm.com        virtual bool
36213590Srekai.gonzalezalberquilla@arm.com        squashed() const override
36313590Srekai.gonzalezalberquilla@arm.com        {
36413590Srekai.gonzalezalberquilla@arm.com            return _inst->isSquashed();
36513590Srekai.gonzalezalberquilla@arm.com        }
36613590Srekai.gonzalezalberquilla@arm.com
36713590Srekai.gonzalezalberquilla@arm.com        /**
36813590Srekai.gonzalezalberquilla@arm.com         * Test if the LSQRequest has been released, i.e. self-owned.
36913590Srekai.gonzalezalberquilla@arm.com         * An LSQRequest manages itself when the resources on the LSQ are freed
37013590Srekai.gonzalezalberquilla@arm.com         * but the translation is still going on and the LSQEntry was freed.
37113590Srekai.gonzalezalberquilla@arm.com         */
37213590Srekai.gonzalezalberquilla@arm.com        bool
37313590Srekai.gonzalezalberquilla@arm.com        isReleased()
37413590Srekai.gonzalezalberquilla@arm.com        {
37513590Srekai.gonzalezalberquilla@arm.com            return flags.isSet(Flag::LSQEntryFreed) ||
37613590Srekai.gonzalezalberquilla@arm.com                flags.isSet(Flag::Discarded);
37713590Srekai.gonzalezalberquilla@arm.com        }
37813590Srekai.gonzalezalberquilla@arm.com
37913590Srekai.gonzalezalberquilla@arm.com        /** Release the LSQRequest.
38013590Srekai.gonzalezalberquilla@arm.com         * Notify the sender state that the request it points to is not valid
38113590Srekai.gonzalezalberquilla@arm.com         * anymore. Understand if the request is orphan (self-managed) and if
38213590Srekai.gonzalezalberquilla@arm.com         * so, mark it as freed, else destroy it, as this means
38313590Srekai.gonzalezalberquilla@arm.com         * the end of its life cycle.
38413590Srekai.gonzalezalberquilla@arm.com         * An LSQRequest is orphan when its resources are released
38513590Srekai.gonzalezalberquilla@arm.com         * but there is any in-flight translation request to the TLB or access
38613590Srekai.gonzalezalberquilla@arm.com         * request to the memory.
38713590Srekai.gonzalezalberquilla@arm.com         */
38813590Srekai.gonzalezalberquilla@arm.com        void release(Flag reason)
38913590Srekai.gonzalezalberquilla@arm.com        {
39013590Srekai.gonzalezalberquilla@arm.com            assert(reason == Flag::LSQEntryFreed || reason == Flag::Discarded);
39113590Srekai.gonzalezalberquilla@arm.com            if (!isAnyOutstandingRequest()) {
39213590Srekai.gonzalezalberquilla@arm.com                delete this;
39313590Srekai.gonzalezalberquilla@arm.com            } else {
39413590Srekai.gonzalezalberquilla@arm.com                if (_senderState) {
39513590Srekai.gonzalezalberquilla@arm.com                    _senderState->deleteRequest();
39613590Srekai.gonzalezalberquilla@arm.com                }
39713590Srekai.gonzalezalberquilla@arm.com                flags.set(reason);
39813590Srekai.gonzalezalberquilla@arm.com            }
39913590Srekai.gonzalezalberquilla@arm.com        }
40013590Srekai.gonzalezalberquilla@arm.com
40113954Sgiacomo.gabrielli@arm.com        /** Helper function used to add a (sub)request, given its address
40213954Sgiacomo.gabrielli@arm.com         * `addr`, size `size` and byte-enable mask `byteEnable`.
40313954Sgiacomo.gabrielli@arm.com         *
40413954Sgiacomo.gabrielli@arm.com         * The request is only added if the mask is empty or if there is at
40513954Sgiacomo.gabrielli@arm.com         * least an active element in it.
40613954Sgiacomo.gabrielli@arm.com         */
40713954Sgiacomo.gabrielli@arm.com        void
40813954Sgiacomo.gabrielli@arm.com        addRequest(Addr addr, unsigned size,
40913954Sgiacomo.gabrielli@arm.com                   const std::vector<bool>& byteEnable)
41013954Sgiacomo.gabrielli@arm.com        {
41113954Sgiacomo.gabrielli@arm.com            if (byteEnable.empty() ||
41213954Sgiacomo.gabrielli@arm.com                isAnyActiveElement(byteEnable.begin(), byteEnable.end())) {
41313954Sgiacomo.gabrielli@arm.com                auto request = std::make_shared<Request>(_inst->getASID(),
41413954Sgiacomo.gabrielli@arm.com                        addr, size, _flags, _inst->masterId(),
41514297Sjordi.vaquero@metempsy.com                        _inst->instAddr(), _inst->contextId(),
41614297Sjordi.vaquero@metempsy.com                        std::move(_amo_op));
41713954Sgiacomo.gabrielli@arm.com                if (!byteEnable.empty()) {
41813954Sgiacomo.gabrielli@arm.com                    request->setByteEnable(byteEnable);
41913954Sgiacomo.gabrielli@arm.com                }
42013954Sgiacomo.gabrielli@arm.com                _requests.push_back(request);
42113954Sgiacomo.gabrielli@arm.com            }
42213954Sgiacomo.gabrielli@arm.com        }
42313954Sgiacomo.gabrielli@arm.com
42413590Srekai.gonzalezalberquilla@arm.com        /** Destructor.
42513590Srekai.gonzalezalberquilla@arm.com         * The LSQRequest owns the request. If the packet has already been
42613590Srekai.gonzalezalberquilla@arm.com         * sent, the sender state will be deleted upon receiving the reply.
42713590Srekai.gonzalezalberquilla@arm.com         */
42813590Srekai.gonzalezalberquilla@arm.com        virtual ~LSQRequest()
42913590Srekai.gonzalezalberquilla@arm.com        {
43013590Srekai.gonzalezalberquilla@arm.com            assert(!isAnyOutstandingRequest());
43113590Srekai.gonzalezalberquilla@arm.com            _inst->savedReq = nullptr;
43213590Srekai.gonzalezalberquilla@arm.com            if (_senderState)
43313590Srekai.gonzalezalberquilla@arm.com                delete _senderState;
43413590Srekai.gonzalezalberquilla@arm.com
43513590Srekai.gonzalezalberquilla@arm.com            for (auto r: _packets)
43613590Srekai.gonzalezalberquilla@arm.com                delete r;
43713590Srekai.gonzalezalberquilla@arm.com        };
43813590Srekai.gonzalezalberquilla@arm.com
43913590Srekai.gonzalezalberquilla@arm.com
44013590Srekai.gonzalezalberquilla@arm.com      public:
44113590Srekai.gonzalezalberquilla@arm.com        /** Convenience getters/setters. */
44213590Srekai.gonzalezalberquilla@arm.com        /** @{ */
44313590Srekai.gonzalezalberquilla@arm.com        /** Set up Context numbers. */
44413590Srekai.gonzalezalberquilla@arm.com        void
44513590Srekai.gonzalezalberquilla@arm.com        setContext(const ContextID& context_id)
44613590Srekai.gonzalezalberquilla@arm.com        {
44713590Srekai.gonzalezalberquilla@arm.com            request()->setContext(context_id);
44813590Srekai.gonzalezalberquilla@arm.com        }
44913590Srekai.gonzalezalberquilla@arm.com
45013590Srekai.gonzalezalberquilla@arm.com        const DynInstPtr&
45113590Srekai.gonzalezalberquilla@arm.com        instruction()
45213590Srekai.gonzalezalberquilla@arm.com        {
45313590Srekai.gonzalezalberquilla@arm.com            return _inst;
45413590Srekai.gonzalezalberquilla@arm.com        }
45513590Srekai.gonzalezalberquilla@arm.com
45613590Srekai.gonzalezalberquilla@arm.com        /** Set up virtual request.
45713590Srekai.gonzalezalberquilla@arm.com         * For a previously allocated Request objects.
45813590Srekai.gonzalezalberquilla@arm.com         */
45913590Srekai.gonzalezalberquilla@arm.com        void
46013590Srekai.gonzalezalberquilla@arm.com        setVirt(int asid, Addr vaddr, unsigned size, Request::Flags flags_,
46113590Srekai.gonzalezalberquilla@arm.com                MasterID mid, Addr pc)
46213590Srekai.gonzalezalberquilla@arm.com        {
46313590Srekai.gonzalezalberquilla@arm.com            request()->setVirt(asid, vaddr, size, flags_, mid, pc);
46413590Srekai.gonzalezalberquilla@arm.com        }
46513590Srekai.gonzalezalberquilla@arm.com
46613590Srekai.gonzalezalberquilla@arm.com        void
46713590Srekai.gonzalezalberquilla@arm.com        taskId(const uint32_t& v)
46813590Srekai.gonzalezalberquilla@arm.com        {
46913590Srekai.gonzalezalberquilla@arm.com            _taskId = v;
47013590Srekai.gonzalezalberquilla@arm.com            for (auto& r: _requests)
47113590Srekai.gonzalezalberquilla@arm.com                r->taskId(v);
47213590Srekai.gonzalezalberquilla@arm.com        }
47313590Srekai.gonzalezalberquilla@arm.com
47413590Srekai.gonzalezalberquilla@arm.com        uint32_t taskId() const { return _taskId; }
47513590Srekai.gonzalezalberquilla@arm.com        RequestPtr request(int idx = 0) { return _requests.at(idx); }
47613590Srekai.gonzalezalberquilla@arm.com
47713590Srekai.gonzalezalberquilla@arm.com        const RequestPtr
47813590Srekai.gonzalezalberquilla@arm.com        request(int idx = 0) const
47913590Srekai.gonzalezalberquilla@arm.com        {
48013590Srekai.gonzalezalberquilla@arm.com            return _requests.at(idx);
48113590Srekai.gonzalezalberquilla@arm.com        }
48213590Srekai.gonzalezalberquilla@arm.com
48313590Srekai.gonzalezalberquilla@arm.com        Addr getVaddr(int idx = 0) const { return request(idx)->getVaddr(); }
48413590Srekai.gonzalezalberquilla@arm.com        virtual void initiateTranslation() = 0;
48513590Srekai.gonzalezalberquilla@arm.com
48613590Srekai.gonzalezalberquilla@arm.com        PacketPtr packet(int idx = 0) { return _packets.at(idx); }
48713590Srekai.gonzalezalberquilla@arm.com
48813590Srekai.gonzalezalberquilla@arm.com        virtual PacketPtr
48913590Srekai.gonzalezalberquilla@arm.com        mainPacket()
49013590Srekai.gonzalezalberquilla@arm.com        {
49113590Srekai.gonzalezalberquilla@arm.com            assert (_packets.size() == 1);
49213590Srekai.gonzalezalberquilla@arm.com            return packet();
49313590Srekai.gonzalezalberquilla@arm.com        }
49413590Srekai.gonzalezalberquilla@arm.com
49513590Srekai.gonzalezalberquilla@arm.com        virtual RequestPtr
49613590Srekai.gonzalezalberquilla@arm.com        mainRequest()
49713590Srekai.gonzalezalberquilla@arm.com        {
49813590Srekai.gonzalezalberquilla@arm.com            assert (_requests.size() == 1);
49913590Srekai.gonzalezalberquilla@arm.com            return request();
50013590Srekai.gonzalezalberquilla@arm.com        }
50113590Srekai.gonzalezalberquilla@arm.com
50213590Srekai.gonzalezalberquilla@arm.com        void
50313590Srekai.gonzalezalberquilla@arm.com        senderState(LSQSenderState* st)
50413590Srekai.gonzalezalberquilla@arm.com        {
50513590Srekai.gonzalezalberquilla@arm.com            _senderState = st;
50613590Srekai.gonzalezalberquilla@arm.com            for (auto& pkt: _packets) {
50713590Srekai.gonzalezalberquilla@arm.com                if (pkt)
50813590Srekai.gonzalezalberquilla@arm.com                    pkt->senderState = st;
50913590Srekai.gonzalezalberquilla@arm.com            }
51013590Srekai.gonzalezalberquilla@arm.com        }
51113590Srekai.gonzalezalberquilla@arm.com
51213590Srekai.gonzalezalberquilla@arm.com        const LSQSenderState*
51313590Srekai.gonzalezalberquilla@arm.com        senderState() const
51413590Srekai.gonzalezalberquilla@arm.com        {
51513590Srekai.gonzalezalberquilla@arm.com            return _senderState;
51613590Srekai.gonzalezalberquilla@arm.com        }
51713590Srekai.gonzalezalberquilla@arm.com
51813590Srekai.gonzalezalberquilla@arm.com        /**
51913590Srekai.gonzalezalberquilla@arm.com         * Mark senderState as discarded. This will cause to discard response
52013590Srekai.gonzalezalberquilla@arm.com         * packets from the cache.
52113590Srekai.gonzalezalberquilla@arm.com         */
52213590Srekai.gonzalezalberquilla@arm.com        void
52313590Srekai.gonzalezalberquilla@arm.com        discardSenderState()
52413590Srekai.gonzalezalberquilla@arm.com        {
52513590Srekai.gonzalezalberquilla@arm.com            assert(_senderState);
52613590Srekai.gonzalezalberquilla@arm.com            _senderState->deleteRequest();
52713590Srekai.gonzalezalberquilla@arm.com        }
52813590Srekai.gonzalezalberquilla@arm.com
52913590Srekai.gonzalezalberquilla@arm.com        /**
53013590Srekai.gonzalezalberquilla@arm.com         * Test if there is any in-flight translation or mem access request
53113590Srekai.gonzalezalberquilla@arm.com         */
53213590Srekai.gonzalezalberquilla@arm.com        bool
53313590Srekai.gonzalezalberquilla@arm.com        isAnyOutstandingRequest()
53413590Srekai.gonzalezalberquilla@arm.com        {
53513590Srekai.gonzalezalberquilla@arm.com            return numInTranslationFragments > 0 ||
53613590Srekai.gonzalezalberquilla@arm.com                _numOutstandingPackets > 0 ||
53713590Srekai.gonzalezalberquilla@arm.com                (flags.isSet(Flag::WritebackScheduled) &&
53813590Srekai.gonzalezalberquilla@arm.com                 !flags.isSet(Flag::WritebackDone));
53913590Srekai.gonzalezalberquilla@arm.com        }
54013590Srekai.gonzalezalberquilla@arm.com
54113590Srekai.gonzalezalberquilla@arm.com        bool
54213590Srekai.gonzalezalberquilla@arm.com        isSplit() const
54313590Srekai.gonzalezalberquilla@arm.com        {
54413590Srekai.gonzalezalberquilla@arm.com            return flags.isSet(Flag::IsSplit);
54513590Srekai.gonzalezalberquilla@arm.com        }
54613590Srekai.gonzalezalberquilla@arm.com        /** @} */
54713590Srekai.gonzalezalberquilla@arm.com        virtual bool recvTimingResp(PacketPtr pkt) = 0;
54813590Srekai.gonzalezalberquilla@arm.com        virtual void sendPacketToCache() = 0;
54913590Srekai.gonzalezalberquilla@arm.com        virtual void buildPackets() = 0;
55013590Srekai.gonzalezalberquilla@arm.com
55113590Srekai.gonzalezalberquilla@arm.com        /**
55213590Srekai.gonzalezalberquilla@arm.com         * Memory mapped IPR accesses
55313590Srekai.gonzalezalberquilla@arm.com         */
55413590Srekai.gonzalezalberquilla@arm.com        virtual void handleIprWrite(ThreadContext *thread, PacketPtr pkt) = 0;
55513590Srekai.gonzalezalberquilla@arm.com        virtual Cycles handleIprRead(ThreadContext *thread, PacketPtr pkt) = 0;
55613590Srekai.gonzalezalberquilla@arm.com
55713590Srekai.gonzalezalberquilla@arm.com        /**
55813590Srekai.gonzalezalberquilla@arm.com         * Test if the request accesses a particular cache line.
55913590Srekai.gonzalezalberquilla@arm.com         */
56013590Srekai.gonzalezalberquilla@arm.com        virtual bool isCacheBlockHit(Addr blockAddr, Addr cacheBlockMask) = 0;
56113590Srekai.gonzalezalberquilla@arm.com
56213590Srekai.gonzalezalberquilla@arm.com        /** Update the status to reflect that a packet was sent. */
56313590Srekai.gonzalezalberquilla@arm.com        void
56413590Srekai.gonzalezalberquilla@arm.com        packetSent()
56513590Srekai.gonzalezalberquilla@arm.com        {
56613590Srekai.gonzalezalberquilla@arm.com            flags.set(Flag::Sent);
56713590Srekai.gonzalezalberquilla@arm.com        }
56813590Srekai.gonzalezalberquilla@arm.com        /** Update the status to reflect that a packet was not sent.
56913590Srekai.gonzalezalberquilla@arm.com         * When a packet fails to be sent, we mark the request as needing a
57013590Srekai.gonzalezalberquilla@arm.com         * retry. Note that Retry flag is sticky.
57113590Srekai.gonzalezalberquilla@arm.com         */
57213590Srekai.gonzalezalberquilla@arm.com        void
57313590Srekai.gonzalezalberquilla@arm.com        packetNotSent()
57413590Srekai.gonzalezalberquilla@arm.com        {
57513590Srekai.gonzalezalberquilla@arm.com            flags.set(Flag::Retry);
57613590Srekai.gonzalezalberquilla@arm.com            flags.clear(Flag::Sent);
57713590Srekai.gonzalezalberquilla@arm.com        }
57813590Srekai.gonzalezalberquilla@arm.com
57913590Srekai.gonzalezalberquilla@arm.com        void sendFragmentToTranslation(int i);
58013590Srekai.gonzalezalberquilla@arm.com        bool
58113590Srekai.gonzalezalberquilla@arm.com        isComplete()
58213590Srekai.gonzalezalberquilla@arm.com        {
58313590Srekai.gonzalezalberquilla@arm.com            return flags.isSet(Flag::Complete);
58413590Srekai.gonzalezalberquilla@arm.com        }
58513590Srekai.gonzalezalberquilla@arm.com
58613590Srekai.gonzalezalberquilla@arm.com        bool
58713590Srekai.gonzalezalberquilla@arm.com        isInTranslation()
58813590Srekai.gonzalezalberquilla@arm.com        {
58913590Srekai.gonzalezalberquilla@arm.com            return _state == State::Translation;
59013590Srekai.gonzalezalberquilla@arm.com        }
59113590Srekai.gonzalezalberquilla@arm.com
59213590Srekai.gonzalezalberquilla@arm.com        bool
59313590Srekai.gonzalezalberquilla@arm.com        isTranslationComplete()
59413590Srekai.gonzalezalberquilla@arm.com        {
59513590Srekai.gonzalezalberquilla@arm.com            return flags.isSet(Flag::TranslationStarted) &&
59613590Srekai.gonzalezalberquilla@arm.com                   !isInTranslation();
59713590Srekai.gonzalezalberquilla@arm.com        }
59813590Srekai.gonzalezalberquilla@arm.com
59913590Srekai.gonzalezalberquilla@arm.com        bool
60013590Srekai.gonzalezalberquilla@arm.com        isTranslationBlocked()
60113590Srekai.gonzalezalberquilla@arm.com        {
60213590Srekai.gonzalezalberquilla@arm.com            return _state == State::Translation &&
60313590Srekai.gonzalezalberquilla@arm.com                flags.isSet(Flag::TranslationStarted) &&
60413590Srekai.gonzalezalberquilla@arm.com                !flags.isSet(Flag::TranslationFinished);
60513590Srekai.gonzalezalberquilla@arm.com        }
60613590Srekai.gonzalezalberquilla@arm.com
60713590Srekai.gonzalezalberquilla@arm.com        bool
60813590Srekai.gonzalezalberquilla@arm.com        isSent()
60913590Srekai.gonzalezalberquilla@arm.com        {
61013590Srekai.gonzalezalberquilla@arm.com            return flags.isSet(Flag::Sent);
61113590Srekai.gonzalezalberquilla@arm.com        }
61213590Srekai.gonzalezalberquilla@arm.com
61314105Sgabor.dozsa@arm.com        bool
61414105Sgabor.dozsa@arm.com        isPartialFault()
61514105Sgabor.dozsa@arm.com        {
61614105Sgabor.dozsa@arm.com            return _state == State::PartialFault;
61714105Sgabor.dozsa@arm.com        }
61814105Sgabor.dozsa@arm.com
61914105Sgabor.dozsa@arm.com        bool
62014105Sgabor.dozsa@arm.com        isMemAccessRequired()
62114105Sgabor.dozsa@arm.com        {
62214105Sgabor.dozsa@arm.com            return (_state == State::Request ||
62314105Sgabor.dozsa@arm.com                    (isPartialFault() && isLoad()));
62414105Sgabor.dozsa@arm.com        }
62514105Sgabor.dozsa@arm.com
62613590Srekai.gonzalezalberquilla@arm.com        /**
62713590Srekai.gonzalezalberquilla@arm.com         * The LSQ entry is cleared
62813590Srekai.gonzalezalberquilla@arm.com         */
62913590Srekai.gonzalezalberquilla@arm.com        void
63013590Srekai.gonzalezalberquilla@arm.com        freeLSQEntry()
63113590Srekai.gonzalezalberquilla@arm.com        {
63213590Srekai.gonzalezalberquilla@arm.com            release(Flag::LSQEntryFreed);
63313590Srekai.gonzalezalberquilla@arm.com        }
63413590Srekai.gonzalezalberquilla@arm.com
63513590Srekai.gonzalezalberquilla@arm.com        /**
63613590Srekai.gonzalezalberquilla@arm.com         * The request is discarded (e.g. partial store-load forwarding)
63713590Srekai.gonzalezalberquilla@arm.com         */
63813590Srekai.gonzalezalberquilla@arm.com        void
63913590Srekai.gonzalezalberquilla@arm.com        discard()
64013590Srekai.gonzalezalberquilla@arm.com        {
64113590Srekai.gonzalezalberquilla@arm.com            release(Flag::Discarded);
64213590Srekai.gonzalezalberquilla@arm.com        }
64313590Srekai.gonzalezalberquilla@arm.com
64413590Srekai.gonzalezalberquilla@arm.com        void
64513590Srekai.gonzalezalberquilla@arm.com        packetReplied()
64613590Srekai.gonzalezalberquilla@arm.com        {
64713590Srekai.gonzalezalberquilla@arm.com            assert(_numOutstandingPackets > 0);
64813590Srekai.gonzalezalberquilla@arm.com            _numOutstandingPackets--;
64913590Srekai.gonzalezalberquilla@arm.com            if (_numOutstandingPackets == 0 && isReleased())
65013590Srekai.gonzalezalberquilla@arm.com                delete this;
65113590Srekai.gonzalezalberquilla@arm.com        }
65213590Srekai.gonzalezalberquilla@arm.com
65313590Srekai.gonzalezalberquilla@arm.com        void
65413590Srekai.gonzalezalberquilla@arm.com        writebackScheduled()
65513590Srekai.gonzalezalberquilla@arm.com        {
65613590Srekai.gonzalezalberquilla@arm.com            assert(!flags.isSet(Flag::WritebackScheduled));
65713590Srekai.gonzalezalberquilla@arm.com            flags.set(Flag::WritebackScheduled);
65813590Srekai.gonzalezalberquilla@arm.com        }
65913590Srekai.gonzalezalberquilla@arm.com
66013590Srekai.gonzalezalberquilla@arm.com        void
66113590Srekai.gonzalezalberquilla@arm.com        writebackDone()
66213590Srekai.gonzalezalberquilla@arm.com        {
66313590Srekai.gonzalezalberquilla@arm.com            flags.set(Flag::WritebackDone);
66413590Srekai.gonzalezalberquilla@arm.com            /* If the lsq resources are already free */
66513590Srekai.gonzalezalberquilla@arm.com            if (isReleased()) {
66613590Srekai.gonzalezalberquilla@arm.com                delete this;
66713590Srekai.gonzalezalberquilla@arm.com            }
66813590Srekai.gonzalezalberquilla@arm.com        }
66913590Srekai.gonzalezalberquilla@arm.com
67013590Srekai.gonzalezalberquilla@arm.com        void
67113590Srekai.gonzalezalberquilla@arm.com        squashTranslation()
67213590Srekai.gonzalezalberquilla@arm.com        {
67313590Srekai.gonzalezalberquilla@arm.com            assert(numInTranslationFragments == 0);
67413590Srekai.gonzalezalberquilla@arm.com            flags.set(Flag::TranslationSquashed);
67513590Srekai.gonzalezalberquilla@arm.com            /* If we are on our own, self-destruct. */
67613590Srekai.gonzalezalberquilla@arm.com            if (isReleased()) {
67713590Srekai.gonzalezalberquilla@arm.com                delete this;
67813590Srekai.gonzalezalberquilla@arm.com            }
67913590Srekai.gonzalezalberquilla@arm.com        }
68013590Srekai.gonzalezalberquilla@arm.com
68113590Srekai.gonzalezalberquilla@arm.com        void
68213590Srekai.gonzalezalberquilla@arm.com        complete()
68313590Srekai.gonzalezalberquilla@arm.com        {
68413590Srekai.gonzalezalberquilla@arm.com            flags.set(Flag::Complete);
68513590Srekai.gonzalezalberquilla@arm.com        }
68613590Srekai.gonzalezalberquilla@arm.com    };
68713590Srekai.gonzalezalberquilla@arm.com
68813590Srekai.gonzalezalberquilla@arm.com    class SingleDataRequest : public LSQRequest
68913590Srekai.gonzalezalberquilla@arm.com    {
69013590Srekai.gonzalezalberquilla@arm.com      protected:
69113590Srekai.gonzalezalberquilla@arm.com        /* Given that we are inside templates, children need explicit
69213590Srekai.gonzalezalberquilla@arm.com         * declaration of the names in the parent class. */
69313590Srekai.gonzalezalberquilla@arm.com        using Flag = typename LSQRequest::Flag;
69413590Srekai.gonzalezalberquilla@arm.com        using State = typename LSQRequest::State;
69513954Sgiacomo.gabrielli@arm.com        using LSQRequest::_addr;
69613590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::_fault;
69713954Sgiacomo.gabrielli@arm.com        using LSQRequest::_flags;
69813954Sgiacomo.gabrielli@arm.com        using LSQRequest::_size;
69913954Sgiacomo.gabrielli@arm.com        using LSQRequest::_byteEnable;
70013954Sgiacomo.gabrielli@arm.com        using LSQRequest::_requests;
70113590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::_inst;
70213590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::_packets;
70313590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::_port;
70413590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::_res;
70513954Sgiacomo.gabrielli@arm.com        using LSQRequest::_taskId;
70613590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::_senderState;
70713590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::_state;
70813590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::flags;
70913590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::isLoad;
71013590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::isTranslationComplete;
71113590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::lsqUnit;
71213590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::request;
71313590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::sendFragmentToTranslation;
71413590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::setState;
71513590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::numInTranslationFragments;
71613590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::numTranslatedFragments;
71713590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::_numOutstandingPackets;
71813652Sqtt2@cornell.edu        using LSQRequest::_amo_op;
71913590Srekai.gonzalezalberquilla@arm.com      public:
72013590Srekai.gonzalezalberquilla@arm.com        SingleDataRequest(LSQUnit* port, const DynInstPtr& inst, bool isLoad,
72113590Srekai.gonzalezalberquilla@arm.com                          const Addr& addr, const uint32_t& size,
72213590Srekai.gonzalezalberquilla@arm.com                          const Request::Flags& flags_,
72313590Srekai.gonzalezalberquilla@arm.com                          PacketDataPtr data = nullptr,
72413652Sqtt2@cornell.edu                          uint64_t* res = nullptr,
72514297Sjordi.vaquero@metempsy.com                          AtomicOpFunctorPtr amo_op = nullptr) :
72613652Sqtt2@cornell.edu            LSQRequest(port, inst, isLoad, addr, size, flags_, data, res,
72714297Sjordi.vaquero@metempsy.com                       std::move(amo_op)) {}
72813954Sgiacomo.gabrielli@arm.com
72913590Srekai.gonzalezalberquilla@arm.com        inline virtual ~SingleDataRequest() {}
73013590Srekai.gonzalezalberquilla@arm.com        virtual void initiateTranslation();
73113590Srekai.gonzalezalberquilla@arm.com        virtual void finish(const Fault &fault, const RequestPtr &req,
73213590Srekai.gonzalezalberquilla@arm.com                ThreadContext* tc, BaseTLB::Mode mode);
73313590Srekai.gonzalezalberquilla@arm.com        virtual bool recvTimingResp(PacketPtr pkt);
73413590Srekai.gonzalezalberquilla@arm.com        virtual void sendPacketToCache();
73513590Srekai.gonzalezalberquilla@arm.com        virtual void buildPackets();
73613590Srekai.gonzalezalberquilla@arm.com        virtual void handleIprWrite(ThreadContext *thread, PacketPtr pkt);
73713590Srekai.gonzalezalberquilla@arm.com        virtual Cycles handleIprRead(ThreadContext *thread, PacketPtr pkt);
73813590Srekai.gonzalezalberquilla@arm.com        virtual bool isCacheBlockHit(Addr blockAddr, Addr cacheBlockMask);
73913590Srekai.gonzalezalberquilla@arm.com    };
74013590Srekai.gonzalezalberquilla@arm.com
74113590Srekai.gonzalezalberquilla@arm.com    class SplitDataRequest : public LSQRequest
74213590Srekai.gonzalezalberquilla@arm.com    {
74313590Srekai.gonzalezalberquilla@arm.com      protected:
74413590Srekai.gonzalezalberquilla@arm.com        /* Given that we are inside templates, children need explicit
74513590Srekai.gonzalezalberquilla@arm.com         * declaration of the names in the parent class. */
74613590Srekai.gonzalezalberquilla@arm.com        using Flag = typename LSQRequest::Flag;
74713590Srekai.gonzalezalberquilla@arm.com        using State = typename LSQRequest::State;
74813590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::_addr;
74913590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::_data;
75013590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::_fault;
75113590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::_flags;
75213590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::_inst;
75313590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::_packets;
75413590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::_port;
75513590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::_requests;
75613590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::_res;
75713954Sgiacomo.gabrielli@arm.com        using LSQRequest::_byteEnable;
75813590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::_senderState;
75913590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::_size;
76013590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::_state;
76113590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::_taskId;
76213590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::flags;
76313590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::isLoad;
76413590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::isTranslationComplete;
76513590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::lsqUnit;
76613590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::numInTranslationFragments;
76713590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::numTranslatedFragments;
76813590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::request;
76913590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::sendFragmentToTranslation;
77013590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::setState;
77113590Srekai.gonzalezalberquilla@arm.com        using LSQRequest::_numOutstandingPackets;
77213590Srekai.gonzalezalberquilla@arm.com
77313590Srekai.gonzalezalberquilla@arm.com        uint32_t numFragments;
77413590Srekai.gonzalezalberquilla@arm.com        uint32_t numReceivedPackets;
77513590Srekai.gonzalezalberquilla@arm.com        RequestPtr mainReq;
77613590Srekai.gonzalezalberquilla@arm.com        PacketPtr _mainPacket;
77713590Srekai.gonzalezalberquilla@arm.com
77813590Srekai.gonzalezalberquilla@arm.com      public:
77913590Srekai.gonzalezalberquilla@arm.com        SplitDataRequest(LSQUnit* port, const DynInstPtr& inst, bool isLoad,
78013590Srekai.gonzalezalberquilla@arm.com                         const Addr& addr, const uint32_t& size,
78113590Srekai.gonzalezalberquilla@arm.com                         const Request::Flags & flags_,
78213590Srekai.gonzalezalberquilla@arm.com                         PacketDataPtr data = nullptr,
78313590Srekai.gonzalezalberquilla@arm.com                         uint64_t* res = nullptr) :
78413954Sgiacomo.gabrielli@arm.com            LSQRequest(port, inst, isLoad, addr, size, flags_, data, res,
78513954Sgiacomo.gabrielli@arm.com                       nullptr),
78613590Srekai.gonzalezalberquilla@arm.com            numFragments(0),
78713590Srekai.gonzalezalberquilla@arm.com            numReceivedPackets(0),
78813590Srekai.gonzalezalberquilla@arm.com            mainReq(nullptr),
78913590Srekai.gonzalezalberquilla@arm.com            _mainPacket(nullptr)
79013590Srekai.gonzalezalberquilla@arm.com        {
79113590Srekai.gonzalezalberquilla@arm.com            flags.set(Flag::IsSplit);
79213590Srekai.gonzalezalberquilla@arm.com        }
79313590Srekai.gonzalezalberquilla@arm.com        virtual ~SplitDataRequest()
79413590Srekai.gonzalezalberquilla@arm.com        {
79513590Srekai.gonzalezalberquilla@arm.com            if (mainReq) {
79613590Srekai.gonzalezalberquilla@arm.com                mainReq = nullptr;
79713590Srekai.gonzalezalberquilla@arm.com            }
79813590Srekai.gonzalezalberquilla@arm.com            if (_mainPacket) {
79913590Srekai.gonzalezalberquilla@arm.com                delete _mainPacket;
80013590Srekai.gonzalezalberquilla@arm.com                _mainPacket = nullptr;
80113590Srekai.gonzalezalberquilla@arm.com            }
80213590Srekai.gonzalezalberquilla@arm.com        }
80313590Srekai.gonzalezalberquilla@arm.com        virtual void finish(const Fault &fault, const RequestPtr &req,
80413590Srekai.gonzalezalberquilla@arm.com                ThreadContext* tc, BaseTLB::Mode mode);
80513590Srekai.gonzalezalberquilla@arm.com        virtual bool recvTimingResp(PacketPtr pkt);
80613590Srekai.gonzalezalberquilla@arm.com        virtual void initiateTranslation();
80713590Srekai.gonzalezalberquilla@arm.com        virtual void sendPacketToCache();
80813590Srekai.gonzalezalberquilla@arm.com        virtual void buildPackets();
80913590Srekai.gonzalezalberquilla@arm.com
81013590Srekai.gonzalezalberquilla@arm.com        virtual void handleIprWrite(ThreadContext *thread, PacketPtr pkt);
81113590Srekai.gonzalezalberquilla@arm.com        virtual Cycles handleIprRead(ThreadContext *thread, PacketPtr pkt);
81213590Srekai.gonzalezalberquilla@arm.com        virtual bool isCacheBlockHit(Addr blockAddr, Addr cacheBlockMask);
81313590Srekai.gonzalezalberquilla@arm.com
81413590Srekai.gonzalezalberquilla@arm.com        virtual RequestPtr mainRequest();
81513590Srekai.gonzalezalberquilla@arm.com        virtual PacketPtr mainPacket();
81613590Srekai.gonzalezalberquilla@arm.com    };
81713590Srekai.gonzalezalberquilla@arm.com
8182292SN/A    /** Constructs an LSQ with the given parameters. */
8195529Snate@binkert.org    LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params);
82013472Srekai.gonzalezalberquilla@arm.com    ~LSQ() { }
8212292SN/A
8222292SN/A    /** Returns the name of the LSQ. */
8232292SN/A    std::string name() const;
8242292SN/A
8252727Sktlim@umich.edu    /** Registers statistics of each LSQ unit. */
8262727Sktlim@umich.edu    void regStats();
8272727Sktlim@umich.edu
8282292SN/A    /** Sets the pointer to the list of active threads. */
8296221Snate@binkert.org    void setActiveThreads(std::list<ThreadID> *at_ptr);
8309444SAndreas.Sandberg@ARM.com
8319444SAndreas.Sandberg@ARM.com    /** Perform sanity checks after a drain. */
8329444SAndreas.Sandberg@ARM.com    void drainSanityCheck() const;
8339444SAndreas.Sandberg@ARM.com    /** Has the LSQ drained? */
8349444SAndreas.Sandberg@ARM.com    bool isDrained() const;
8352348SN/A    /** Takes over execution from another CPU's thread. */
8362307SN/A    void takeOverFrom();
8372307SN/A
8382292SN/A    /** Number of entries needed for the given amount of threads.*/
8396221Snate@binkert.org    int entryAmount(ThreadID num_threads);
8402292SN/A
8412292SN/A    /** Ticks the LSQ. */
84213710Sgabor.dozsa@arm.com    void tick();
8432292SN/A
8442292SN/A    /** Inserts a load into the LSQ. */
84513429Srekai.gonzalezalberquilla@arm.com    void insertLoad(const DynInstPtr &load_inst);
8462292SN/A    /** Inserts a store into the LSQ. */
84713429Srekai.gonzalezalberquilla@arm.com    void insertStore(const DynInstPtr &store_inst);
8482292SN/A
8492292SN/A    /** Executes a load. */
85013429Srekai.gonzalezalberquilla@arm.com    Fault executeLoad(const DynInstPtr &inst);
8512292SN/A
8522292SN/A    /** Executes a store. */
85313429Srekai.gonzalezalberquilla@arm.com    Fault executeStore(const DynInstPtr &inst);
8542292SN/A
8552292SN/A    /**
8562292SN/A     * Commits loads up until the given sequence number for a specific thread.
8572292SN/A     */
8586221Snate@binkert.org    void commitLoads(InstSeqNum &youngest_inst, ThreadID tid)
85913590Srekai.gonzalezalberquilla@arm.com    { thread.at(tid).commitLoads(youngest_inst); }
8602329SN/A
8612292SN/A    /**
8622292SN/A     * Commits stores up until the given sequence number for a specific thread.
8632292SN/A     */
8646221Snate@binkert.org    void commitStores(InstSeqNum &youngest_inst, ThreadID tid)
86513590Srekai.gonzalezalberquilla@arm.com    { thread.at(tid).commitStores(youngest_inst); }
8662292SN/A
8672292SN/A    /**
8682292SN/A     * Attempts to write back stores until all cache ports are used or the
8692292SN/A     * interface becomes blocked.
8702292SN/A     */
8712292SN/A    void writebackStores();
8722292SN/A    /** Same as above, but only for one thread. */
8736221Snate@binkert.org    void writebackStores(ThreadID tid);
8742292SN/A
8752292SN/A    /**
8762292SN/A     * Squash instructions from a thread until the specified sequence number.
8772292SN/A     */
87813590Srekai.gonzalezalberquilla@arm.com    void
87913590Srekai.gonzalezalberquilla@arm.com    squash(const InstSeqNum &squashed_num, ThreadID tid)
88013590Srekai.gonzalezalberquilla@arm.com    {
88113590Srekai.gonzalezalberquilla@arm.com        thread.at(tid).squash(squashed_num);
88213590Srekai.gonzalezalberquilla@arm.com    }
8832292SN/A
8842292SN/A    /** Returns whether or not there was a memory ordering violation. */
8852292SN/A    bool violation();
8862292SN/A    /**
8872292SN/A     * Returns whether or not there was a memory ordering violation for a
8882292SN/A     * specific thread.
8892292SN/A     */
89013590Srekai.gonzalezalberquilla@arm.com    bool violation(ThreadID tid) { return thread.at(tid).violation(); }
8912292SN/A
8922292SN/A    /** Gets the instruction that caused the memory ordering violation. */
89313590Srekai.gonzalezalberquilla@arm.com    DynInstPtr
89413590Srekai.gonzalezalberquilla@arm.com    getMemDepViolator(ThreadID tid)
89513590Srekai.gonzalezalberquilla@arm.com    {
89613590Srekai.gonzalezalberquilla@arm.com        return thread.at(tid).getMemDepViolator();
89713590Srekai.gonzalezalberquilla@arm.com    }
8982292SN/A
8992292SN/A    /** Returns the head index of the load queue for a specific thread. */
90013590Srekai.gonzalezalberquilla@arm.com    int getLoadHead(ThreadID tid) { return thread.at(tid).getLoadHead(); }
9012329SN/A
9022292SN/A    /** Returns the sequence number of the head of the load queue. */
90313590Srekai.gonzalezalberquilla@arm.com    InstSeqNum
90413590Srekai.gonzalezalberquilla@arm.com    getLoadHeadSeqNum(ThreadID tid)
9052292SN/A    {
90613590Srekai.gonzalezalberquilla@arm.com        return thread.at(tid).getLoadHeadSeqNum();
9072292SN/A    }
9082292SN/A
9092292SN/A    /** Returns the head index of the store queue. */
91013590Srekai.gonzalezalberquilla@arm.com    int getStoreHead(ThreadID tid) { return thread.at(tid).getStoreHead(); }
9112329SN/A
9122292SN/A    /** Returns the sequence number of the head of the store queue. */
91313590Srekai.gonzalezalberquilla@arm.com    InstSeqNum
91413590Srekai.gonzalezalberquilla@arm.com    getStoreHeadSeqNum(ThreadID tid)
9152292SN/A    {
91613590Srekai.gonzalezalberquilla@arm.com        return thread.at(tid).getStoreHeadSeqNum();
9172292SN/A    }
9182292SN/A
9192292SN/A    /** Returns the number of instructions in all of the queues. */
9202292SN/A    int getCount();
9212292SN/A    /** Returns the number of instructions in the queues of one thread. */
92213590Srekai.gonzalezalberquilla@arm.com    int getCount(ThreadID tid) { return thread.at(tid).getCount(); }
9232292SN/A
9242292SN/A    /** Returns the total number of loads in the load queue. */
9252292SN/A    int numLoads();
9262292SN/A    /** Returns the total number of loads for a single thread. */
92713590Srekai.gonzalezalberquilla@arm.com    int numLoads(ThreadID tid) { return thread.at(tid).numLoads(); }
9282292SN/A
9292292SN/A    /** Returns the total number of stores in the store queue. */
9302292SN/A    int numStores();
9312292SN/A    /** Returns the total number of stores for a single thread. */
93213590Srekai.gonzalezalberquilla@arm.com    int numStores(ThreadID tid) { return thread.at(tid).numStores(); }
9332292SN/A
93410239Sbinhpham@cs.rutgers.edu    /** Returns the number of free load entries. */
93510239Sbinhpham@cs.rutgers.edu    unsigned numFreeLoadEntries();
93610239Sbinhpham@cs.rutgers.edu
93710239Sbinhpham@cs.rutgers.edu    /** Returns the number of free store entries. */
93810239Sbinhpham@cs.rutgers.edu    unsigned numFreeStoreEntries();
93910239Sbinhpham@cs.rutgers.edu
9402292SN/A    /** Returns the number of free entries for a specific thread. */
9416221Snate@binkert.org    unsigned numFreeEntries(ThreadID tid);
9422292SN/A
94310239Sbinhpham@cs.rutgers.edu    /** Returns the number of free entries in the LQ for a specific thread. */
94410239Sbinhpham@cs.rutgers.edu    unsigned numFreeLoadEntries(ThreadID tid);
94510239Sbinhpham@cs.rutgers.edu
94610239Sbinhpham@cs.rutgers.edu    /** Returns the number of free entries in the SQ for a specific thread. */
94710239Sbinhpham@cs.rutgers.edu    unsigned numFreeStoreEntries(ThreadID tid);
94810239Sbinhpham@cs.rutgers.edu
9492292SN/A    /** Returns if the LSQ is full (either LQ or SQ is full). */
9502292SN/A    bool isFull();
9512292SN/A    /**
9522292SN/A     * Returns if the LSQ is full for a specific thread (either LQ or SQ is
9532292SN/A     * full).
9542292SN/A     */
9556221Snate@binkert.org    bool isFull(ThreadID tid);
9562292SN/A
9579444SAndreas.Sandberg@ARM.com    /** Returns if the LSQ is empty (both LQ and SQ are empty). */
9589444SAndreas.Sandberg@ARM.com    bool isEmpty() const;
9599444SAndreas.Sandberg@ARM.com    /** Returns if all of the LQs are empty. */
9609444SAndreas.Sandberg@ARM.com    bool lqEmpty() const;
9619444SAndreas.Sandberg@ARM.com    /** Returns if all of the SQs are empty. */
9629444SAndreas.Sandberg@ARM.com    bool sqEmpty() const;
9639444SAndreas.Sandberg@ARM.com
9642292SN/A    /** Returns if any of the LQs are full. */
9652292SN/A    bool lqFull();
9662292SN/A    /** Returns if the LQ of a given thread is full. */
9676221Snate@binkert.org    bool lqFull(ThreadID tid);
9682292SN/A
9692292SN/A    /** Returns if any of the SQs are full. */
9702292SN/A    bool sqFull();
9712292SN/A    /** Returns if the SQ of a given thread is full. */
9726221Snate@binkert.org    bool sqFull(ThreadID tid);
9732292SN/A
9742292SN/A    /**
9752292SN/A     * Returns if the LSQ is stalled due to a memory operation that must be
9762292SN/A     * replayed.
9772292SN/A     */
9782292SN/A    bool isStalled();
9792292SN/A    /**
9802292SN/A     * Returns if the LSQ of a specific thread is stalled due to a memory
9812292SN/A     * operation that must be replayed.
9822292SN/A     */
9836221Snate@binkert.org    bool isStalled(ThreadID tid);
9842292SN/A
9852292SN/A    /** Returns whether or not there are any stores to write back to memory. */
9862292SN/A    bool hasStoresToWB();
9872329SN/A
9882292SN/A    /** Returns whether or not a specific thread has any stores to write back
9892292SN/A     * to memory.
9902292SN/A     */
99113590Srekai.gonzalezalberquilla@arm.com    bool hasStoresToWB(ThreadID tid) { return thread.at(tid).hasStoresToWB(); }
9922329SN/A
9932292SN/A    /** Returns the number of stores a specific thread has to write back. */
99413590Srekai.gonzalezalberquilla@arm.com    int numStoresToWB(ThreadID tid) { return thread.at(tid).numStoresToWB(); }
9952292SN/A
9962292SN/A    /** Returns if the LSQ will write back to memory this cycle. */
9972292SN/A    bool willWB();
9982292SN/A    /** Returns if the LSQ of a specific thread will write back to memory this
9992292SN/A     * cycle.
10002292SN/A     */
100113590Srekai.gonzalezalberquilla@arm.com    bool willWB(ThreadID tid) { return thread.at(tid).willWB(); }
10022292SN/A
10032292SN/A    /** Debugging function to print out all instructions. */
10049440SAndreas.Sandberg@ARM.com    void dumpInsts() const;
10052292SN/A    /** Debugging function to print out instructions from a specific thread. */
100613590Srekai.gonzalezalberquilla@arm.com    void dumpInsts(ThreadID tid) const { thread.at(tid).dumpInsts(); }
10072292SN/A
10086974Stjones1@inf.ed.ac.uk    /** Executes a read operation, using the load specified at the load
10096974Stjones1@inf.ed.ac.uk     * index.
10106974Stjones1@inf.ed.ac.uk     */
101113590Srekai.gonzalezalberquilla@arm.com    Fault read(LSQRequest* req, int load_idx);
10122292SN/A
10132292SN/A    /** Executes a store operation, using the store specified at the store
10146974Stjones1@inf.ed.ac.uk     * index.
10152292SN/A     */
101613590Srekai.gonzalezalberquilla@arm.com    Fault write(LSQRequest* req, uint8_t *data, int store_idx);
10172292SN/A
10188707Sandreas.hansson@arm.com    /**
10198707Sandreas.hansson@arm.com     * Retry the previous send that failed.
10208707Sandreas.hansson@arm.com     */
102110713Sandreas.hansson@arm.com    void recvReqRetry();
10228707Sandreas.hansson@arm.com
102313590Srekai.gonzalezalberquilla@arm.com    void completeDataAccess(PacketPtr pkt);
10248707Sandreas.hansson@arm.com    /**
10258707Sandreas.hansson@arm.com     * Handles writing back and completing the load or store that has
10268707Sandreas.hansson@arm.com     * returned from memory.
10278707Sandreas.hansson@arm.com     *
10288707Sandreas.hansson@arm.com     * @param pkt Response packet from the memory sub-system
10298707Sandreas.hansson@arm.com     */
10308975Sandreas.hansson@arm.com    bool recvTimingResp(PacketPtr pkt);
10318707Sandreas.hansson@arm.com
10328975Sandreas.hansson@arm.com    void recvTimingSnoopReq(PacketPtr pkt);
10338948Sandreas.hansson@arm.com
103413590Srekai.gonzalezalberquilla@arm.com    Fault pushRequest(const DynInstPtr& inst, bool isLoad, uint8_t *data,
103513590Srekai.gonzalezalberquilla@arm.com                      unsigned int size, Addr addr, Request::Flags flags,
103614297Sjordi.vaquero@metempsy.com                      uint64_t *res, AtomicOpFunctorPtr amo_op,
103713954Sgiacomo.gabrielli@arm.com                      const std::vector<bool>& byteEnable);
103813590Srekai.gonzalezalberquilla@arm.com
10394329Sktlim@umich.edu    /** The CPU pointer. */
10404329Sktlim@umich.edu    O3CPU *cpu;
10414329Sktlim@umich.edu
10424329Sktlim@umich.edu    /** The IEW stage pointer. */
10434329Sktlim@umich.edu    IEW *iewStage;
10444329Sktlim@umich.edu
104513590Srekai.gonzalezalberquilla@arm.com    /** Is D-cache blocked? */
104613590Srekai.gonzalezalberquilla@arm.com    bool cacheBlocked() const;
104713590Srekai.gonzalezalberquilla@arm.com    /** Set D-cache blocked status */
104813590Srekai.gonzalezalberquilla@arm.com    void cacheBlocked(bool v);
104913590Srekai.gonzalezalberquilla@arm.com    /** Is any store port available to use? */
105013710Sgabor.dozsa@arm.com    bool cachePortAvailable(bool is_load) const;
105113590Srekai.gonzalezalberquilla@arm.com    /** Another store port is in use */
105213710Sgabor.dozsa@arm.com    void cachePortBusy(bool is_load);
105313590Srekai.gonzalezalberquilla@arm.com
105414194Sgabeblack@google.com    MasterPort &getDataPort() { return dcachePort; }
105514194Sgabeblack@google.com
10562907Sktlim@umich.edu  protected:
105713590Srekai.gonzalezalberquilla@arm.com    /** D-cache is blocked */
105813590Srekai.gonzalezalberquilla@arm.com    bool _cacheBlocked;
105913590Srekai.gonzalezalberquilla@arm.com    /** The number of cache ports available each cycle (stores only). */
106013590Srekai.gonzalezalberquilla@arm.com    int cacheStorePorts;
106113590Srekai.gonzalezalberquilla@arm.com    /** The number of used cache ports in this cycle by stores. */
106213590Srekai.gonzalezalberquilla@arm.com    int usedStorePorts;
106313710Sgabor.dozsa@arm.com    /** The number of cache ports available each cycle (loads only). */
106413710Sgabor.dozsa@arm.com    int cacheLoadPorts;
106513710Sgabor.dozsa@arm.com    /** The number of used cache ports in this cycle by loads. */
106613710Sgabor.dozsa@arm.com    int usedLoadPorts;
106713590Srekai.gonzalezalberquilla@arm.com
106813590Srekai.gonzalezalberquilla@arm.com
10692292SN/A    /** The LSQ policy for SMT mode. */
107013560Snikos.nikoleris@arm.com    SMTQueuePolicy lsqPolicy;
107113472Srekai.gonzalezalberquilla@arm.com
107213472Srekai.gonzalezalberquilla@arm.com    /** Auxiliary function to calculate per-thread max LSQ allocation limit.
107313472Srekai.gonzalezalberquilla@arm.com     * Depending on a policy, number of entries and possibly number of threads
107413472Srekai.gonzalezalberquilla@arm.com     * and threshold, this function calculates how many resources each thread
107513472Srekai.gonzalezalberquilla@arm.com     * can occupy at most.
107613472Srekai.gonzalezalberquilla@arm.com     */
107713590Srekai.gonzalezalberquilla@arm.com    static uint32_t
107813590Srekai.gonzalezalberquilla@arm.com    maxLSQAllocation(SMTQueuePolicy pol, uint32_t entries,
107913590Srekai.gonzalezalberquilla@arm.com            uint32_t numThreads, uint32_t SMTThreshold)
108013590Srekai.gonzalezalberquilla@arm.com    {
108113560Snikos.nikoleris@arm.com        if (pol == SMTQueuePolicy::Dynamic) {
108213472Srekai.gonzalezalberquilla@arm.com            return entries;
108313560Snikos.nikoleris@arm.com        } else if (pol == SMTQueuePolicy::Partitioned) {
108413472Srekai.gonzalezalberquilla@arm.com            //@todo:make work if part_amt doesnt divide evenly.
108513472Srekai.gonzalezalberquilla@arm.com            return entries / numThreads;
108613560Snikos.nikoleris@arm.com        } else if (pol == SMTQueuePolicy::Threshold) {
108713472Srekai.gonzalezalberquilla@arm.com            //Divide up by threshold amount
108813472Srekai.gonzalezalberquilla@arm.com            //@todo: Should threads check the max and the total
108913472Srekai.gonzalezalberquilla@arm.com            //amount of the LSQ
109013472Srekai.gonzalezalberquilla@arm.com            return SMTThreshold;
109113472Srekai.gonzalezalberquilla@arm.com        }
109213472Srekai.gonzalezalberquilla@arm.com        return 0;
109313472Srekai.gonzalezalberquilla@arm.com    }
10942292SN/A
10952292SN/A    /** List of Active Threads in System. */
10966221Snate@binkert.org    std::list<ThreadID> *activeThreads;
10972292SN/A
10982292SN/A    /** Total Size of LQ Entries. */
10992292SN/A    unsigned LQEntries;
11002292SN/A    /** Total Size of SQ Entries. */
11012292SN/A    unsigned SQEntries;
11022292SN/A
11032292SN/A    /** Max LQ Size - Used to Enforce Sharing Policies. */
11042292SN/A    unsigned maxLQEntries;
11052292SN/A
11062292SN/A    /** Max SQ Size - Used to Enforce Sharing Policies. */
11072292SN/A    unsigned maxSQEntries;
11082292SN/A
110914194Sgabeblack@google.com    /** Data port. */
111014194Sgabeblack@google.com    DcachePort dcachePort;
111114194Sgabeblack@google.com
111213472Srekai.gonzalezalberquilla@arm.com    /** The LSQ units for individual threads. */
111313472Srekai.gonzalezalberquilla@arm.com    std::vector<LSQUnit> thread;
111413472Srekai.gonzalezalberquilla@arm.com
11152292SN/A    /** Number of Threads. */
11166221Snate@binkert.org    ThreadID numThreads;
11172292SN/A};
11182292SN/A
11192292SN/Atemplate <class Impl>
11202292SN/AFault
112113590Srekai.gonzalezalberquilla@arm.comLSQ<Impl>::read(LSQRequest* req, int load_idx)
11222292SN/A{
112313590Srekai.gonzalezalberquilla@arm.com    ThreadID tid = cpu->contextToThread(req->request()->contextId());
11242292SN/A
112513590Srekai.gonzalezalberquilla@arm.com    return thread.at(tid).read(req, load_idx);
11262292SN/A}
11272292SN/A
11282292SN/Atemplate <class Impl>
11292292SN/AFault
113013590Srekai.gonzalezalberquilla@arm.comLSQ<Impl>::write(LSQRequest* req, uint8_t *data, int store_idx)
11312292SN/A{
113213590Srekai.gonzalezalberquilla@arm.com    ThreadID tid = cpu->contextToThread(req->request()->contextId());
11332292SN/A
113413590Srekai.gonzalezalberquilla@arm.com    return thread.at(tid).write(req, data, store_idx);
11352292SN/A}
11362292SN/A
11372292SN/A#endif // __CPU_O3_LSQ_HH__
1138