/*
 * Copyright (c) 2013-2014, 2018 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @file
 *
 *  A load/store queue that allows outstanding reads and writes.
 *
 */

#ifndef __CPU_MINOR_NEW_LSQ_HH__
#define __CPU_MINOR_NEW_LSQ_HH__

#include "cpu/minor/buffers.hh"
#include "cpu/minor/cpu.hh"
#include "cpu/minor/pipe_data.hh"
#include "cpu/minor/trace.hh"

namespace Minor
{

/* Forward declaration */
class Execute;

class LSQ : public Named
{
  protected:
    /** My owner(s) */
    MinorCPU &cpu;
    Execute &execute;

  protected:
    /** State of memory access for head access. */
    enum MemoryState
    {
        MemoryRunning, /* Default. Step dcache queues when possible. */
        MemoryNeedsRetry /* Request rejected, will be asked to retry */
    };

    /** Print MemoryState values as shown in the enum definition */
    friend std::ostream &operator <<(std::ostream &os,
        MemoryState state);

    /** Coverage of one address range with another */
    enum AddrRangeCoverage
    {
        PartialAddrRangeCoverage, /* Two ranges partly overlap */
        FullAddrRangeCoverage, /* One range fully covers another */
        NoAddrRangeCoverage /* Two ranges are disjoint */
    };

    /** Exposable data port */
    class DcachePort : public MinorCPU::MinorCPUPort
    {
      protected:
        /** My owner */
        LSQ &lsq;

      public:
        DcachePort(std::string name, LSQ &lsq_, MinorCPU &cpu) :
            MinorCPU::MinorCPUPort(name, cpu), lsq(lsq_)
        { }

      protected:
        bool recvTimingResp(PacketPtr pkt) override
        { return lsq.recvTimingResp(pkt); }

        void recvReqRetry() override { lsq.recvReqRetry(); }

        bool isSnooping() const override { return true; }

        void recvTimingSnoopReq(PacketPtr pkt) override
        { return lsq.recvTimingSnoopReq(pkt); }

        void recvFunctionalSnoop(PacketPtr pkt) override { }
    };

    DcachePort dcachePort;

  public:
    /** Derived SenderState to carry data access info. through address
     *  translation, the queues in this port and back from the memory
     *  system. */
    class LSQRequest :
        public BaseTLB::Translation, /* For TLB lookups */
        public Packet::SenderState /* For packing into a Packet */
    {
      public:
        /** Owning port */
        LSQ &port;

        /** Instruction which made this request */
        MinorDynInstPtr inst;

        /** Load/store indication used for building packet.  This isn't
         *  carried by Request so we need to keep it here */
        bool isLoad;

        /** Dynamically allocated and populated data carried for
         *  building write packets */
        PacketDataPtr data;

        /* Requests carry packets on their way to the memory system.
         *  When a Packet returns from the memory system, its
         *  request needs to have its packet updated as this
         *  may have changed in flight */
        PacketPtr packet;

        /** The underlying request of this LSQRequest */
        RequestPtr request;

        /** Res from pushRequest */
        uint64_t *res;

        /** Was skipped.  Set to indicate any reason (faulted, bad
         *  stream sequence number, in a fault shadow) that this
         *  request did not perform a memory transfer */
        bool skipped;

        /** This in an access other than a normal cacheable load
         *  that's visited the memory system */
        bool issuedToMemory;

        /** Address translation is delayed due to table walk */
        bool isTranslationDelayed;

        enum LSQRequestState
        {
            NotIssued, /* Newly created */
            InTranslation, /* TLB accessed, no reply yet */
            Translated, /* Finished address translation */
            Failed, /* The starting start of FailedDataRequests */
            RequestIssuing, /* Load/store issued to memory in the requests
                queue */
            StoreToStoreBuffer, /* Store in transfers on its way to the
                store buffer */
            RequestNeedsRetry, /* Retry needed for load */
            StoreInStoreBuffer, /* Store in the store buffer, before issuing
                a memory transfer */
            StoreBufferIssuing, /* Store in store buffer and has been
                issued */
            StoreBufferNeedsRetry, /* Retry needed for store */
            /* All completed states.  Includes
                completed loads, TLB faults and skipped requests whose
                seqNum's no longer match */
            Complete
        };

        LSQRequestState state;

      protected:
        /** BaseTLB::Translation interface */
        void markDelayed() { isTranslationDelayed = true; }

        /** Instructions may want to suppress translation faults (e.g.
         *  non-faulting vector loads).*/
        void tryToSuppressFault();

        void disableMemAccess();
        void completeDisabledMemAccess();

      public:
        LSQRequest(LSQ &port_, MinorDynInstPtr inst_, bool isLoad_,
            PacketDataPtr data_ = NULL, uint64_t *res_ = NULL);

        virtual ~LSQRequest();

      public:
        /** Make a packet to use with the memory transaction */
        void makePacket();

        /** Was no memory access attempted for this request? */
        bool skippedMemAccess() { return skipped; }

        /** Set this request as having been skipped before a memory
         *  transfer was attempt */
        void setSkipped() { skipped = true; }

        /** Does address range req1 (req1_addr to req1_addr + req1_size - 1)
         *  fully cover, partially cover or not cover at all the range req2 */
        static AddrRangeCoverage containsAddrRangeOf(
            Addr req1_addr, unsigned int req1_size,
            Addr req2_addr, unsigned int req2_size);

        /** Does this request's address range fully cover the range
         *  of other_request? */
        AddrRangeCoverage containsAddrRangeOf(LSQRequest *other_request);

        /** Start the address translation process for this request.  This
         *  will issue a translation request to the TLB. */
        virtual void startAddrTranslation() = 0;

        /** Get the next packet to issue for this request.  For split
         *  transfers, it will be necessary to step through the available
         *  packets by calling do { getHeadPacket ; stepToNextPacket } while
         *  (!sentAllPackets) and by retiring response using retireResponse */
        virtual PacketPtr getHeadPacket() = 0;

        /** Step to the next packet for the next call to getHeadPacket */
        virtual void stepToNextPacket() = 0;

        /** Have all packets been sent? */
        virtual bool sentAllPackets() = 0;

        /** True if this request has any issued packets in the memory
         *  system and so can't be interrupted until it gets responses */
        virtual bool hasPacketsInMemSystem() = 0;

        /** Retire a response packet into the LSQRequest packet possibly
         *  completing this transfer */
        virtual void retireResponse(PacketPtr packet_) = 0;

        /** Is this a request a barrier? */
        virtual bool isBarrier();

        /** This request, once processed by the requests/transfers
         *  queues, will need to go to the store buffer */
        bool needsToBeSentToStoreBuffer();

        /** Set state and output trace output */
        void setState(LSQRequestState new_state);

        /** Has this request been completed.  This includes *all* reasons
         *  for completion: successful transfers, faults, skipped because
         *  of preceding faults */
        bool isComplete() const;

        /** MinorTrace report interface */
        void reportData(std::ostream &os) const;
    };

    typedef LSQRequest *LSQRequestPtr;

    friend std::ostream & operator <<(std::ostream &os,
        AddrRangeCoverage state);

    friend std::ostream & operator <<(std::ostream &os,
        LSQRequest::LSQRequestState state);

  protected:
    /** Special request types that don't actually issue memory requests */
    class SpecialDataRequest : public LSQRequest
    {
      protected:
        /** TLB interace */
        void finish(const Fault &fault_, const RequestPtr &request_,
                    ThreadContext *tc, BaseTLB::Mode mode)
        { }

      public:
        /** Send single translation request */
        void startAddrTranslation() { }

        /** Get the head packet as counted by numIssuedFragments */
        PacketPtr getHeadPacket()
        { fatal("No packets in a SpecialDataRequest"); }

        /** Step on numIssuedFragments */
        void stepToNextPacket() { }

        /** Has no packets to send */
        bool sentAllPackets() { return true; }

        /** Never sends any requests */
        bool hasPacketsInMemSystem() { return false; }

        /** Keep the given packet as the response packet
         *  LSQRequest::packet */
        void retireResponse(PacketPtr packet_) { }

      public:
        SpecialDataRequest(LSQ &port_, MinorDynInstPtr inst_) :
            /* Say this is a load, not actually relevant */
            LSQRequest(port_, inst_, true, NULL, 0)
        { }
    };

    /** FailedDataRequest represents requests from instructions that
     *  failed their predicates but need to ride the requests/transfers
     *  queues to maintain trace ordering */
    class FailedDataRequest : public SpecialDataRequest
    {
      public:
        FailedDataRequest(LSQ &port_, MinorDynInstPtr inst_) :
            SpecialDataRequest(port_, inst_)
        { state = Failed; }
    };

    /** Request for doing barrier accounting in the store buffer.  Not
     *  for use outside that unit */
    class BarrierDataRequest : public SpecialDataRequest
    {
      public:
        bool isBarrier() { return true; }

      public:
        BarrierDataRequest(LSQ &port_, MinorDynInstPtr inst_) :
            SpecialDataRequest(port_, inst_)
        { state = Complete; }
    };

    /** SingleDataRequest is used for requests that don't fragment */
    class SingleDataRequest : public LSQRequest
    {
      protected:
        /** TLB interace */
        void finish(const Fault &fault_, const RequestPtr &request_,
                    ThreadContext *tc, BaseTLB::Mode mode);

        /** Has my only packet been sent to the memory system but has not
         *  yet been responded to */
        bool packetInFlight;

        /** Has the packet been at least sent to the memory system? */
        bool packetSent;

      public:
        /** Send single translation request */
        void startAddrTranslation();

        /** Get the head packet as counted by numIssuedFragments */
        PacketPtr getHeadPacket() { return packet; }

        /** Remember that the packet has been sent */
        void stepToNextPacket() { packetInFlight = true; packetSent = true; }

        /** Has packet been sent */
        bool hasPacketsInMemSystem() { return packetInFlight; }

        /** packetInFlight can become false again, so need to check
         *  packetSent */
        bool sentAllPackets() { return packetSent; }

        /** Keep the given packet as the response packet
         *  LSQRequest::packet */
        void retireResponse(PacketPtr packet_);

      public:
        SingleDataRequest(LSQ &port_, MinorDynInstPtr inst_,
            bool isLoad_, PacketDataPtr data_ = NULL, uint64_t *res_ = NULL) :
            LSQRequest(port_, inst_, isLoad_, data_, res_),
            packetInFlight(false),
            packetSent(false)
        { }
    };

    class SplitDataRequest : public LSQRequest
    {
      protected:
        /** Event to step between translations */
        EventFunctionWrapper translationEvent;
      protected:
        /** Number of fragments this request is split into */
        unsigned int numFragments;

        /** Number of fragments in the address translation mechanism */
        unsigned int numInTranslationFragments;

        /** Number of fragments that have completed address translation,
         *  (numTranslatedFragments + numInTranslationFragments) <=
         *  numFragments.  When numTranslatedFramgents == numFragments,
         *  translation is complete */
        unsigned int numTranslatedFragments;

        /** Number of fragments already issued (<= numFragments) */
        unsigned int numIssuedFragments;

        /** Number of fragments retired back to this request */
        unsigned int numRetiredFragments;

        /** Fragment Requests corresponding to the address ranges of
         *  each fragment */
        std::vector<RequestPtr> fragmentRequests;

        /** Packets matching fragmentRequests to issue fragments to memory */
        std::vector<Packet *> fragmentPackets;

      protected:
        /** TLB response interface */
        void finish(const Fault &fault_, const RequestPtr &request_,
                    ThreadContext *tc, BaseTLB::Mode mode);

      public:
        SplitDataRequest(LSQ &port_, MinorDynInstPtr inst_,
            bool isLoad_, PacketDataPtr data_ = NULL,
            uint64_t *res_ = NULL);

        ~SplitDataRequest();

      public:
        /** Make all the Requests for this transfer's fragments so that those
         *  requests can be sent for address translation */
        void makeFragmentRequests();

        /** Make the packets to go with the requests so they can be sent to
         *  the memory system */
        void makeFragmentPackets();

        /** Start a loop of do { sendNextFragmentToTranslation ;
         *  translateTiming ; finish } while (numTranslatedFragments !=
         *  numFragments) to complete all this requests' fragments' address
         *  translations */
        void startAddrTranslation();

        /** Get the head packet as counted by numIssuedFragments */
        PacketPtr getHeadPacket();

        /** Step on numIssuedFragments */
        void stepToNextPacket();

        bool hasPacketsInMemSystem()
        { return numIssuedFragments != numRetiredFragments; }

        /** Have we stepped past the end of fragmentPackets? */
        bool sentAllPackets()
        { return numIssuedFragments == numTranslatedFragments; }

        /** For loads, paste the response data into the main
         *  response packet */
        void retireResponse(PacketPtr packet_);

        /** Part of the address translation loop, see startAddTranslation */
        void sendNextFragmentToTranslation();
    };

    /** Store buffer.  This contains stores which have been committed
     *  but whose memory transfers have not yet been issued. Load data
     *  can be forwarded out of the store buffer */
    class StoreBuffer : public Named
    {
      public:
        /** My owner */
        LSQ &lsq;

        /** Number of slots, this is a bound on the size of slots */
        const unsigned int numSlots;

        /** Maximum number of stores that can be issued per cycle */
        const unsigned int storeLimitPerCycle;

      public:
        /** Queue of store requests on their way to memory */
        std::deque<LSQRequestPtr> slots;

        /** Number of occupied slots which have not yet issued a
         *  memory access */
        unsigned int numUnissuedAccesses;

      public:
        StoreBuffer(std::string name_, LSQ &lsq_,
            unsigned int store_buffer_size,
            unsigned int store_limit_per_cycle);

      public:
        /** Can a new request be inserted into the queue? */
        bool canInsert() const;

        /** Delete the given request and free the slot it occupied */
        void deleteRequest(LSQRequestPtr request);

        /** Insert a request at the back of the queue */
        void insert(LSQRequestPtr request);

        /** Look for a store which satisfies the given load.  Returns an
         *  indication whether the forwarding request can be wholly,
         *  partly or not all all satisfied.  If the request can be
         *  wholly satisfied, the store buffer slot number which can be used
         *  is returned in found_slot */
        AddrRangeCoverage canForwardDataToLoad(LSQRequestPtr request,
            unsigned int &found_slot);

        /** Fill the given packet with appropriate date from slot
         *  slot_number */
        void forwardStoreData(LSQRequestPtr load, unsigned int slot_number);

        /** Number of stores in the store buffer which have not been
         *  completely issued to the memory system */
        unsigned int numUnissuedStores() { return numUnissuedAccesses; }

        /** Count a store being issued to memory by decrementing
         *  numUnissuedAccesses.  Does not count barrier requests as they
         *  will be handles as barriers are cleared from the buffer */
        void countIssuedStore(LSQRequestPtr request);

        /** Drained if there is absolutely nothing left in the buffer */
        bool isDrained() const { return slots.empty(); }

        /** Try to issue more stores to memory */
        void step();

        /** Report queue contents for MinorTrace */
        void minorTrace() const;
    };

  protected:
    /** Most recent execSeqNum of a memory barrier instruction or
     *  0 if there are no in-flight barriers.  Useful as a
     *  dependency for early-issued memory operations */
    std::vector<InstSeqNum> lastMemBarrier;

  public:
    /** Retry state of last issued memory transfer */
    MemoryState state;

    /** Maximum number of in-flight accesses issued to the memory system */
    const unsigned int inMemorySystemLimit;

    /** Memory system access width (and snap) in bytes */
    const unsigned int lineWidth;

  public:
    /** The LSQ consists of three queues: requests, transfers and the
     *  store buffer storeBuffer. */

    typedef Queue<LSQRequestPtr,
        ReportTraitsPtrAdaptor<LSQRequestPtr>,
        NoBubbleTraits<LSQRequestPtr> >
        LSQQueue;

    /** requests contains LSQRequests which have been issued to the TLB by
     *  calling ExecContext::readMem/writeMem (which in turn calls
     *  LSQ::pushRequest and LSQRequest::startAddrTranslation).  Once they
     *  have a physical address, requests at the head of requests can be
     *  issued to the memory system.  At this stage, it cannot be clear that
     *  memory accesses *must* happen (that there are no preceding faults or
     *  changes of flow of control) and so only cacheable reads are issued
     *  to memory.
     *  Cacheable stores are not issued at all (and just pass through
     *  'transfers' in order) and all other transfers are stalled in requests
     *  until their corresponding instructions are at the head of the
     *  inMemInsts instruction queue and have the right streamSeqNum. */
    LSQQueue requests;

    /** Once issued to memory (or, for stores, just had their
     *  state changed to StoreToStoreBuffer) LSQRequests pass through
     *  transfers waiting for memory responses.  At the head of transfers,
     *  Execute::commitInst can pick up the memory response for a request
     *  using LSQ::findResponse.  Responses to be committed can then
     *  have ExecContext::completeAcc on them.  Stores can then be pushed
     *  into the store buffer.  All other transfers will then be complete. */
    LSQQueue transfers;

    /* The store buffer contains committed cacheable stores on
     * their way to memory decoupled from subsequence instruction execution.
     * Before trying to issue a cacheable read from 'requests' to memory,
     * the store buffer is checked to see if a previous store contains the
     * needed data (StoreBuffer::canForwardDataToLoad) which can be
     * forwarded in lieu of a memory access.  If there are outstanding
     * stores in the transfers queue, they must be promoted to the store
     * buffer (and so be commited) before they can be correctly checked
     * for forwarding. */
    StoreBuffer storeBuffer;

  protected:
    /** Count of the number of mem. accesses which have left the
     *  requests queue and are in the 'wild' in the memory system and who
     *  *must not* be interrupted as they are not normal cacheable
     *  accesses.  This is a count of the number of in-flight requests
     *  with issuedToMemory set who have visited tryToSendRequest at least
     *  once */
    unsigned int numAccessesInMemorySystem;

    /** Number of requests in the DTLB in the requests queue */
    unsigned int numAccessesInDTLB;

    /** The number of stores in the transfers queue.  Useful when
     *  testing if the store buffer contains all the forwardable stores */
    unsigned int numStoresInTransfers;

    /** The number of accesses which have been issued to the memory
     *  system but have not been committed/discarded *excluding*
     *  cacheable normal loads which don't need to be tracked */
    unsigned int numAccessesIssuedToMemory;

    /** The request (from either requests or the store buffer) which is
     *  currently waiting have its memory access retried */
    LSQRequestPtr retryRequest;

    /** Address Mask for a cache block (e.g. ~(cache_block_size-1)) */
    Addr cacheBlockMask;

  protected:
    /** Try and issue a memory access for a translated request at the
     *  head of the requests queue.  Also tries to move the request
     *  between queues */
    void tryToSendToTransfers(LSQRequestPtr request);

    /** Try to send (or resend) a memory request's next/only packet to
     *  the memory system.  Returns true if the request was successfully
     *  sent to memory (and was also the last packet in a transfer) */
    bool tryToSend(LSQRequestPtr request);

    /** Clear a barrier (if it's the last one marked up in lastMemBarrier) */
    void clearMemBarrier(MinorDynInstPtr inst);

    /** Move a request between queues */
    void moveFromRequestsToTransfers(LSQRequestPtr request);

    /** Can a request be sent to the memory system */
    bool canSendToMemorySystem();

    /** Snoop other threads monitors on memory system accesses */
    void threadSnoop(LSQRequestPtr request);

  public:
    LSQ(std::string name_, std::string dcache_port_name_,
        MinorCPU &cpu_, Execute &execute_,
        unsigned int max_accesses_in_memory_system, unsigned int line_width,
        unsigned int requests_queue_size, unsigned int transfers_queue_size,
        unsigned int store_buffer_size,
        unsigned int store_buffer_cycle_store_limit);

    virtual ~LSQ();

  public:
    /** Step checks the queues to see if their are issuable transfers
     *  which were not otherwise picked up by tests at the end of other
     *  events.
     *
     *  Steppable actions include deferred actions which couldn't be
     *  cascaded on the end of a memory response/TLB response event
     *  because of resource congestion. */
    void step();

    /** Is their space in the request queue to be able to push a request by
     *  issuing an isMemRef instruction */
    bool canRequest() { return requests.unreservedRemainingSpace() != 0; }

    /** Returns a response if it's at the head of the transfers queue and
     *  it's either complete or can be sent on to the store buffer.  After
     *  calling, the request still remains on the transfer queue until
     *  popResponse is called */
    LSQRequestPtr findResponse(MinorDynInstPtr inst);

    /** Sanity check and pop the head response */
    void popResponse(LSQRequestPtr response);

    /** Must check this before trying to insert into the store buffer */
    bool canPushIntoStoreBuffer() const { return storeBuffer.canInsert(); }

    /** A store has been committed, please move it to the store buffer */
    void sendStoreToStoreBuffer(LSQRequestPtr request);

    /** Are there any accesses other than normal cached loads in the
     *  memory system or having received responses which need to be
     *  handled for their instruction's to be completed */
    bool accessesInFlight() const
    { return numAccessesIssuedToMemory != 0; }

    /** A memory barrier instruction has been issued, remember its
     *  execSeqNum that we can avoid issuing memory ops until it is
     *  committed */
    void issuedMemBarrierInst(MinorDynInstPtr inst);

    /** Get the execSeqNum of the last issued memory barrier */
    InstSeqNum getLastMemBarrier(ThreadID thread_id) const
    { return lastMemBarrier[thread_id]; }

    /** Is there nothing left in the LSQ */
    bool isDrained();

    /** May need to be ticked next cycle as one of the queues contains
     *  an actionable transfers or address translation */
    bool needsToTick();

    /** Complete a barrier instruction.  Where committed, makes a
     *  BarrierDataRequest and pushed it into the store buffer */
    void completeMemBarrierInst(MinorDynInstPtr inst,
        bool committed);

    /** Single interface for readMem/writeMem/amoMem to issue requests into
     *  the LSQ */
    Fault pushRequest(MinorDynInstPtr inst, bool isLoad, uint8_t *data,
                      unsigned int size, Addr addr, Request::Flags flags,
                      uint64_t *res, AtomicOpFunctorPtr amo_op,
                      const std::vector<bool>& byte_enable =
                          std::vector<bool>());

    /** Push a predicate failed-representing request into the queues just
     *  to maintain commit order */
    void pushFailedRequest(MinorDynInstPtr inst);

    /** Memory interface */
    bool recvTimingResp(PacketPtr pkt);
    void recvReqRetry();
    void recvTimingSnoopReq(PacketPtr pkt);

    /** Return the raw-bindable port */
    MinorCPU::MinorCPUPort &getDcachePort() { return dcachePort; }

    void minorTrace() const;
};

/** Make a suitable packet for the given request.  If the request is a store,
 *  data will be the payload data.  If sender_state is NULL, it won't be
 *  pushed into the packet as senderState */
PacketPtr makePacketForRequest(const RequestPtr &request, bool isLoad,
    Packet::SenderState *sender_state = NULL, PacketDataPtr data = NULL);
}

#endif /* __CPU_MINOR_NEW_LSQ_HH__ */
