lsq.hh revision 10713
110259SAndrew.Bardsley@arm.com/*
210259SAndrew.Bardsley@arm.com * Copyright (c) 2013-2014 ARM Limited
310259SAndrew.Bardsley@arm.com * All rights reserved
410259SAndrew.Bardsley@arm.com *
510259SAndrew.Bardsley@arm.com * The license below extends only to copyright in the software and shall
610259SAndrew.Bardsley@arm.com * not be construed as granting a license to any other intellectual
710259SAndrew.Bardsley@arm.com * property including but not limited to intellectual property relating
810259SAndrew.Bardsley@arm.com * to a hardware implementation of the functionality of the software
910259SAndrew.Bardsley@arm.com * licensed hereunder.  You may use the software subject to the license
1010259SAndrew.Bardsley@arm.com * terms below provided that you ensure that this notice is replicated
1110259SAndrew.Bardsley@arm.com * unmodified and in its entirety in all distributions of the software,
1210259SAndrew.Bardsley@arm.com * modified or unmodified, in source code or in binary form.
1310259SAndrew.Bardsley@arm.com *
1410259SAndrew.Bardsley@arm.com * Redistribution and use in source and binary forms, with or without
1510259SAndrew.Bardsley@arm.com * modification, are permitted provided that the following conditions are
1610259SAndrew.Bardsley@arm.com * met: redistributions of source code must retain the above copyright
1710259SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer;
1810259SAndrew.Bardsley@arm.com * redistributions in binary form must reproduce the above copyright
1910259SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer in the
2010259SAndrew.Bardsley@arm.com * documentation and/or other materials provided with the distribution;
2110259SAndrew.Bardsley@arm.com * neither the name of the copyright holders nor the names of its
2210259SAndrew.Bardsley@arm.com * contributors may be used to endorse or promote products derived from
2310259SAndrew.Bardsley@arm.com * this software without specific prior written permission.
2410259SAndrew.Bardsley@arm.com *
2510259SAndrew.Bardsley@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2610259SAndrew.Bardsley@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2710259SAndrew.Bardsley@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2810259SAndrew.Bardsley@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2910259SAndrew.Bardsley@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3010259SAndrew.Bardsley@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3110259SAndrew.Bardsley@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3210259SAndrew.Bardsley@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3310259SAndrew.Bardsley@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3410259SAndrew.Bardsley@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3510259SAndrew.Bardsley@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3610259SAndrew.Bardsley@arm.com *
3710259SAndrew.Bardsley@arm.com * Authors: Andrew Bardsley
3810259SAndrew.Bardsley@arm.com */
3910259SAndrew.Bardsley@arm.com
4010259SAndrew.Bardsley@arm.com/**
4110259SAndrew.Bardsley@arm.com * @file
4210259SAndrew.Bardsley@arm.com *
4310259SAndrew.Bardsley@arm.com *  A load/store queue that allows outstanding reads and writes.
4410259SAndrew.Bardsley@arm.com *
4510259SAndrew.Bardsley@arm.com */
4610259SAndrew.Bardsley@arm.com
4710259SAndrew.Bardsley@arm.com#ifndef __CPU_MINOR_NEW_LSQ_HH__
4810259SAndrew.Bardsley@arm.com#define __CPU_MINOR_NEW_LSQ_HH__
4910259SAndrew.Bardsley@arm.com
5010259SAndrew.Bardsley@arm.com#include "cpu/minor/buffers.hh"
5110259SAndrew.Bardsley@arm.com#include "cpu/minor/cpu.hh"
5210259SAndrew.Bardsley@arm.com#include "cpu/minor/pipe_data.hh"
5310259SAndrew.Bardsley@arm.com#include "cpu/minor/trace.hh"
5410259SAndrew.Bardsley@arm.com
5510259SAndrew.Bardsley@arm.comnamespace Minor
5610259SAndrew.Bardsley@arm.com{
5710259SAndrew.Bardsley@arm.com
5810259SAndrew.Bardsley@arm.com/* Forward declaration */
5910259SAndrew.Bardsley@arm.comclass Execute;
6010259SAndrew.Bardsley@arm.com
6110259SAndrew.Bardsley@arm.comclass LSQ : public Named
6210259SAndrew.Bardsley@arm.com{
6310259SAndrew.Bardsley@arm.com  protected:
6410259SAndrew.Bardsley@arm.com    /** My owner(s) */
6510259SAndrew.Bardsley@arm.com    MinorCPU &cpu;
6610259SAndrew.Bardsley@arm.com    Execute &execute;
6710259SAndrew.Bardsley@arm.com
6810259SAndrew.Bardsley@arm.com  protected:
6910259SAndrew.Bardsley@arm.com    /** State of memory access for head access. */
7010259SAndrew.Bardsley@arm.com    enum MemoryState
7110259SAndrew.Bardsley@arm.com    {
7210259SAndrew.Bardsley@arm.com        MemoryRunning, /* Default. Step dcache queues when possible. */
7310259SAndrew.Bardsley@arm.com        MemoryNeedsRetry /* Request rejected, will be asked to retry */
7410259SAndrew.Bardsley@arm.com    };
7510259SAndrew.Bardsley@arm.com
7610259SAndrew.Bardsley@arm.com    /** Print MemoryState values as shown in the enum definition */
7710259SAndrew.Bardsley@arm.com    friend std::ostream &operator <<(std::ostream &os,
7810259SAndrew.Bardsley@arm.com        MemoryState state);
7910259SAndrew.Bardsley@arm.com
8010259SAndrew.Bardsley@arm.com    /** Coverage of one address range with another */
8110259SAndrew.Bardsley@arm.com    enum AddrRangeCoverage
8210259SAndrew.Bardsley@arm.com    {
8310259SAndrew.Bardsley@arm.com        PartialAddrRangeCoverage, /* Two ranges partly overlap */
8410259SAndrew.Bardsley@arm.com        FullAddrRangeCoverage, /* One range fully covers another */
8510259SAndrew.Bardsley@arm.com        NoAddrRangeCoverage /* Two ranges are disjoint */
8610259SAndrew.Bardsley@arm.com    };
8710259SAndrew.Bardsley@arm.com
8810259SAndrew.Bardsley@arm.com    /** Exposable data port */
8910259SAndrew.Bardsley@arm.com    class DcachePort : public MinorCPU::MinorCPUPort
9010259SAndrew.Bardsley@arm.com    {
9110259SAndrew.Bardsley@arm.com      protected:
9210259SAndrew.Bardsley@arm.com        /** My owner */
9310259SAndrew.Bardsley@arm.com        LSQ &lsq;
9410259SAndrew.Bardsley@arm.com
9510259SAndrew.Bardsley@arm.com      public:
9610259SAndrew.Bardsley@arm.com        DcachePort(std::string name, LSQ &lsq_, MinorCPU &cpu) :
9710259SAndrew.Bardsley@arm.com            MinorCPU::MinorCPUPort(name, cpu), lsq(lsq_)
9810259SAndrew.Bardsley@arm.com        { }
9910259SAndrew.Bardsley@arm.com
10010259SAndrew.Bardsley@arm.com      protected:
10110259SAndrew.Bardsley@arm.com        bool recvTimingResp(PacketPtr pkt)
10210259SAndrew.Bardsley@arm.com        { return lsq.recvTimingResp(pkt); }
10310259SAndrew.Bardsley@arm.com
10410259SAndrew.Bardsley@arm.com        void recvReqRetry() { lsq.recvReqRetry(); }
10510259SAndrew.Bardsley@arm.com
10610259SAndrew.Bardsley@arm.com        void recvTimingSnoopReq(PacketPtr pkt)
10710259SAndrew.Bardsley@arm.com        { return lsq.recvTimingSnoopReq(pkt); }
10810259SAndrew.Bardsley@arm.com    };
10910259SAndrew.Bardsley@arm.com
11010259SAndrew.Bardsley@arm.com    DcachePort dcachePort;
11110259SAndrew.Bardsley@arm.com
11210259SAndrew.Bardsley@arm.com  public:
11311567Smitch.hayenga@arm.com    /** Derived SenderState to carry data access info. through address
11411567Smitch.hayenga@arm.com     *  translation, the queues in this port and back from the memory
11511567Smitch.hayenga@arm.com     *  system. */
11610259SAndrew.Bardsley@arm.com    class LSQRequest :
11710259SAndrew.Bardsley@arm.com        public BaseTLB::Translation, /* For TLB lookups */
11810259SAndrew.Bardsley@arm.com        public Packet::SenderState /* For packing into a Packet */
11910259SAndrew.Bardsley@arm.com    {
12010259SAndrew.Bardsley@arm.com      public:
12110259SAndrew.Bardsley@arm.com        /** Owning port */
12210259SAndrew.Bardsley@arm.com        LSQ &port;
12310259SAndrew.Bardsley@arm.com
12410259SAndrew.Bardsley@arm.com        /** Instruction which made this request */
12510259SAndrew.Bardsley@arm.com        MinorDynInstPtr inst;
12610259SAndrew.Bardsley@arm.com
12710259SAndrew.Bardsley@arm.com        /** Load/store indication used for building packet.  This isn't
12811567Smitch.hayenga@arm.com         *  carried by Request so we need to keep it here */
12910259SAndrew.Bardsley@arm.com        bool isLoad;
13010259SAndrew.Bardsley@arm.com
13110259SAndrew.Bardsley@arm.com        /** Dynamically allocated and populated data carried for
13210259SAndrew.Bardsley@arm.com         *  building write packets */
13310259SAndrew.Bardsley@arm.com        PacketDataPtr data;
13410259SAndrew.Bardsley@arm.com
13511567Smitch.hayenga@arm.com        /* Requests carry packets on their way to the memory system.
13610259SAndrew.Bardsley@arm.com         *  When a Packet returns from the memory system, its
13710259SAndrew.Bardsley@arm.com         *  request needs to have its packet updated as this
13810259SAndrew.Bardsley@arm.com         *  may have changed in flight */
13910259SAndrew.Bardsley@arm.com        PacketPtr packet;
14010259SAndrew.Bardsley@arm.com
14111567Smitch.hayenga@arm.com        /** The underlying request of this LSQRequest */
14210259SAndrew.Bardsley@arm.com        Request request;
14310259SAndrew.Bardsley@arm.com
14410259SAndrew.Bardsley@arm.com        /** Fault generated performing this request */
14510259SAndrew.Bardsley@arm.com        Fault fault;
14610259SAndrew.Bardsley@arm.com
14710259SAndrew.Bardsley@arm.com        /** Res from pushRequest */
14810259SAndrew.Bardsley@arm.com        uint64_t *res;
14910259SAndrew.Bardsley@arm.com
15010259SAndrew.Bardsley@arm.com        /** Was skipped.  Set to indicate any reason (faulted, bad
15110259SAndrew.Bardsley@arm.com         *  stream sequence number, in a fault shadow) that this
15210259SAndrew.Bardsley@arm.com         *  request did not perform a memory transfer */
15310259SAndrew.Bardsley@arm.com        bool skipped;
15410259SAndrew.Bardsley@arm.com
15510259SAndrew.Bardsley@arm.com        /** This in an access other than a normal cacheable load
15610259SAndrew.Bardsley@arm.com         *  that's visited the memory system */
15710259SAndrew.Bardsley@arm.com        bool issuedToMemory;
15810259SAndrew.Bardsley@arm.com
15910259SAndrew.Bardsley@arm.com        enum LSQRequestState
16010259SAndrew.Bardsley@arm.com        {
16110259SAndrew.Bardsley@arm.com            NotIssued, /* Newly created */
16210259SAndrew.Bardsley@arm.com            InTranslation, /* TLB accessed, no reply yet */
16310259SAndrew.Bardsley@arm.com            Translated, /* Finished address translation */
16410259SAndrew.Bardsley@arm.com            Failed, /* The starting start of FailedDataRequests */
16510259SAndrew.Bardsley@arm.com            RequestIssuing, /* Load/store issued to memory in the requests
16610259SAndrew.Bardsley@arm.com                queue */
16710259SAndrew.Bardsley@arm.com            StoreToStoreBuffer, /* Store in transfers on its way to the
16810259SAndrew.Bardsley@arm.com                store buffer */
16910259SAndrew.Bardsley@arm.com            RequestNeedsRetry, /* Retry needed for load */
17010259SAndrew.Bardsley@arm.com            StoreInStoreBuffer, /* Store in the store buffer, before issuing
17110259SAndrew.Bardsley@arm.com                a memory transfer */
17210259SAndrew.Bardsley@arm.com            StoreBufferIssuing, /* Store in store buffer and has been
17310259SAndrew.Bardsley@arm.com                issued */
17410259SAndrew.Bardsley@arm.com            StoreBufferNeedsRetry, /* Retry needed for store */
17510259SAndrew.Bardsley@arm.com            /* All completed states.  Includes
17610259SAndrew.Bardsley@arm.com                completed loads, TLB faults and skipped requests whose
17710259SAndrew.Bardsley@arm.com                seqNum's no longer match */
17810259SAndrew.Bardsley@arm.com            Complete
17910259SAndrew.Bardsley@arm.com        };
18010259SAndrew.Bardsley@arm.com
18110259SAndrew.Bardsley@arm.com        LSQRequestState state;
18210259SAndrew.Bardsley@arm.com
18310259SAndrew.Bardsley@arm.com      protected:
18410259SAndrew.Bardsley@arm.com        /** BaseTLB::Translation interface */
18510259SAndrew.Bardsley@arm.com        void markDelayed() { }
18610259SAndrew.Bardsley@arm.com
18710259SAndrew.Bardsley@arm.com      public:
18810259SAndrew.Bardsley@arm.com        LSQRequest(LSQ &port_, MinorDynInstPtr inst_, bool isLoad_,
18910259SAndrew.Bardsley@arm.com            PacketDataPtr data_ = NULL, uint64_t *res_ = NULL);
19010259SAndrew.Bardsley@arm.com
19110259SAndrew.Bardsley@arm.com        virtual ~LSQRequest();
19210259SAndrew.Bardsley@arm.com
19310259SAndrew.Bardsley@arm.com      public:
19410259SAndrew.Bardsley@arm.com        /** Make a packet to use with the memory transaction */
19510259SAndrew.Bardsley@arm.com        void makePacket();
19610259SAndrew.Bardsley@arm.com
19710259SAndrew.Bardsley@arm.com        /** Was no memory access attempted for this request? */
19810259SAndrew.Bardsley@arm.com        bool skippedMemAccess() { return skipped; }
19910259SAndrew.Bardsley@arm.com
20010259SAndrew.Bardsley@arm.com        /** Set this request as having been skipped before a memory
20110259SAndrew.Bardsley@arm.com         *  transfer was attempt */
20210259SAndrew.Bardsley@arm.com        void setSkipped() { skipped = true; }
20310259SAndrew.Bardsley@arm.com
20410259SAndrew.Bardsley@arm.com        /** Does address range req1 (req1_addr to req1_addr + req1_size - 1)
20510259SAndrew.Bardsley@arm.com         *  fully cover, partially cover or not cover at all the range req2 */
20610259SAndrew.Bardsley@arm.com        static AddrRangeCoverage containsAddrRangeOf(
20710259SAndrew.Bardsley@arm.com            Addr req1_addr, unsigned int req1_size,
20810259SAndrew.Bardsley@arm.com            Addr req2_addr, unsigned int req2_size);
20910259SAndrew.Bardsley@arm.com
21010259SAndrew.Bardsley@arm.com        /** Does this request's address range fully cover the range
21110259SAndrew.Bardsley@arm.com         *  of other_request? */
21210259SAndrew.Bardsley@arm.com        AddrRangeCoverage containsAddrRangeOf(LSQRequest *other_request);
21310259SAndrew.Bardsley@arm.com
21410259SAndrew.Bardsley@arm.com        /** Start the address translation process for this request.  This
21510259SAndrew.Bardsley@arm.com         *  will issue a translation request to the TLB. */
21610259SAndrew.Bardsley@arm.com        virtual void startAddrTranslation() = 0;
21710259SAndrew.Bardsley@arm.com
21810259SAndrew.Bardsley@arm.com        /** Get the next packet to issue for this request.  For split
21910259SAndrew.Bardsley@arm.com         *  transfers, it will be necessary to step through the available
22010259SAndrew.Bardsley@arm.com         *  packets by calling do { getHeadPacket ; stepToNextPacket } while
22110259SAndrew.Bardsley@arm.com         *  (!sentAllPackets) and by retiring response using retireResponse */
22210259SAndrew.Bardsley@arm.com        virtual PacketPtr getHeadPacket() = 0;
22310259SAndrew.Bardsley@arm.com
22410259SAndrew.Bardsley@arm.com        /** Step to the next packet for the next call to getHeadPacket */
22510259SAndrew.Bardsley@arm.com        virtual void stepToNextPacket() = 0;
22610259SAndrew.Bardsley@arm.com
22710259SAndrew.Bardsley@arm.com        /** Have all packets been sent? */
22810259SAndrew.Bardsley@arm.com        virtual bool sentAllPackets() = 0;
22910259SAndrew.Bardsley@arm.com
23010259SAndrew.Bardsley@arm.com        /** True if this request has any issued packets in the memory
23110259SAndrew.Bardsley@arm.com         *  system and so can't be interrupted until it gets responses */
23210259SAndrew.Bardsley@arm.com        virtual bool hasPacketsInMemSystem() = 0;
23310259SAndrew.Bardsley@arm.com
23410259SAndrew.Bardsley@arm.com        /** Retire a response packet into the LSQRequest packet possibly
23510259SAndrew.Bardsley@arm.com         *  completing this transfer */
23610259SAndrew.Bardsley@arm.com        virtual void retireResponse(PacketPtr packet_) = 0;
23710259SAndrew.Bardsley@arm.com
23810259SAndrew.Bardsley@arm.com        /** Is this a request a barrier? */
23910259SAndrew.Bardsley@arm.com        virtual bool isBarrier();
24010259SAndrew.Bardsley@arm.com
24110259SAndrew.Bardsley@arm.com        /** This request, once processed by the requests/transfers
24210259SAndrew.Bardsley@arm.com         *  queues, will need to go to the store buffer */
24310259SAndrew.Bardsley@arm.com        bool needsToBeSentToStoreBuffer();
24410259SAndrew.Bardsley@arm.com
24510259SAndrew.Bardsley@arm.com        /** Set state and output trace output */
24610259SAndrew.Bardsley@arm.com        void setState(LSQRequestState new_state);
24710259SAndrew.Bardsley@arm.com
24810259SAndrew.Bardsley@arm.com        /** Has this request been completed.  This includes *all* reasons
24910259SAndrew.Bardsley@arm.com         *  for completion: successful transfers, faults, skipped because
25010259SAndrew.Bardsley@arm.com         *  of preceding faults */
25110259SAndrew.Bardsley@arm.com        bool isComplete() const;
25210259SAndrew.Bardsley@arm.com
25310259SAndrew.Bardsley@arm.com        /** MinorTrace report interface */
25410259SAndrew.Bardsley@arm.com        void reportData(std::ostream &os) const;
25510259SAndrew.Bardsley@arm.com    };
25610259SAndrew.Bardsley@arm.com
25710259SAndrew.Bardsley@arm.com    typedef LSQRequest *LSQRequestPtr;
25810259SAndrew.Bardsley@arm.com
25910259SAndrew.Bardsley@arm.com    friend std::ostream & operator <<(std::ostream &os,
26010259SAndrew.Bardsley@arm.com        AddrRangeCoverage state);
26110259SAndrew.Bardsley@arm.com
26210259SAndrew.Bardsley@arm.com    friend std::ostream & operator <<(std::ostream &os,
26310259SAndrew.Bardsley@arm.com        LSQRequest::LSQRequestState state);
26411567Smitch.hayenga@arm.com
26511567Smitch.hayenga@arm.com  protected:
26611567Smitch.hayenga@arm.com    /** Special request types that don't actually issue memory requests */
26710259SAndrew.Bardsley@arm.com    class SpecialDataRequest : public LSQRequest
26811567Smitch.hayenga@arm.com    {
26911567Smitch.hayenga@arm.com      protected:
27010259SAndrew.Bardsley@arm.com        /** TLB interace */
27110259SAndrew.Bardsley@arm.com        void finish(const Fault &fault_, RequestPtr request_,
27210259SAndrew.Bardsley@arm.com                    ThreadContext *tc, BaseTLB::Mode mode)
27310259SAndrew.Bardsley@arm.com        { }
27410259SAndrew.Bardsley@arm.com
27510259SAndrew.Bardsley@arm.com      public:
27610259SAndrew.Bardsley@arm.com        /** Send single translation request */
27710259SAndrew.Bardsley@arm.com        void startAddrTranslation() { }
27810259SAndrew.Bardsley@arm.com
27910259SAndrew.Bardsley@arm.com        /** Get the head packet as counted by numIssuedFragments */
28010259SAndrew.Bardsley@arm.com        PacketPtr getHeadPacket()
28110259SAndrew.Bardsley@arm.com        { fatal("No packets in a SpecialDataRequest"); }
28210259SAndrew.Bardsley@arm.com
28310259SAndrew.Bardsley@arm.com        /** Step on numIssuedFragments */
28410259SAndrew.Bardsley@arm.com        void stepToNextPacket() { }
28510259SAndrew.Bardsley@arm.com
28610259SAndrew.Bardsley@arm.com        /** Has no packets to send */
28710259SAndrew.Bardsley@arm.com        bool sentAllPackets() { return true; }
28810259SAndrew.Bardsley@arm.com
28910259SAndrew.Bardsley@arm.com        /** Never sends any requests */
29010259SAndrew.Bardsley@arm.com        bool hasPacketsInMemSystem() { return false; }
29110259SAndrew.Bardsley@arm.com
29210259SAndrew.Bardsley@arm.com        /** Keep the given packet as the response packet
29310259SAndrew.Bardsley@arm.com         *  LSQRequest::packet */
29410259SAndrew.Bardsley@arm.com        void retireResponse(PacketPtr packet_) { }
29510259SAndrew.Bardsley@arm.com
296      public:
297        SpecialDataRequest(LSQ &port_, MinorDynInstPtr inst_) :
298            /* Say this is a load, not actually relevant */
299            LSQRequest(port_, inst_, true, NULL, 0)
300        { }
301    };
302
303    /** FailedDataRequest represents requests from instructions that
304     *  failed their predicates but need to ride the requests/transfers
305     *  queues to maintain trace ordering */
306    class FailedDataRequest : public SpecialDataRequest
307    {
308      public:
309        FailedDataRequest(LSQ &port_, MinorDynInstPtr inst_) :
310            SpecialDataRequest(port_, inst_)
311        { state = Failed; }
312    };
313
314    /** Request for doing barrier accounting in the store buffer.  Not
315     *  for use outside that unit */
316    class BarrierDataRequest : public SpecialDataRequest
317    {
318      public:
319        bool isBarrier() { return true; }
320
321      public:
322        BarrierDataRequest(LSQ &port_, MinorDynInstPtr inst_) :
323            SpecialDataRequest(port_, inst_)
324        { state = Complete; }
325    };
326
327    /** SingleDataRequest is used for requests that don't fragment */
328    class SingleDataRequest : public LSQRequest
329    {
330      protected:
331        /** TLB interace */
332        void finish(const Fault &fault_, RequestPtr request_,
333                    ThreadContext *tc, BaseTLB::Mode mode);
334
335        /** Has my only packet been sent to the memory system but has not
336         *  yet been responded to */
337        bool packetInFlight;
338
339        /** Has the packet been at least sent to the memory system? */
340        bool packetSent;
341
342      public:
343        /** Send single translation request */
344        void startAddrTranslation();
345
346        /** Get the head packet as counted by numIssuedFragments */
347        PacketPtr getHeadPacket() { return packet; }
348
349        /** Remember that the packet has been sent */
350        void stepToNextPacket() { packetInFlight = true; packetSent = true; }
351
352        /** Has packet been sent */
353        bool hasPacketsInMemSystem() { return packetInFlight; }
354
355        /** packetInFlight can become false again, so need to check
356         *  packetSent */
357        bool sentAllPackets() { return packetSent; }
358
359        /** Keep the given packet as the response packet
360         *  LSQRequest::packet */
361        void retireResponse(PacketPtr packet_);
362
363      public:
364        SingleDataRequest(LSQ &port_, MinorDynInstPtr inst_,
365            bool isLoad_, PacketDataPtr data_ = NULL, uint64_t *res_ = NULL) :
366            LSQRequest(port_, inst_, isLoad_, data_, res_),
367            packetInFlight(false),
368            packetSent(false)
369        { }
370    };
371
372    class SplitDataRequest : public LSQRequest
373    {
374      protected:
375        /** Event to step between translations */
376        class TranslationEvent : public Event
377        {
378          protected:
379            SplitDataRequest &owner;
380
381          public:
382            TranslationEvent(SplitDataRequest &owner_)
383                : owner(owner_) { }
384
385            void process()
386            { owner.sendNextFragmentToTranslation(); }
387        };
388
389        TranslationEvent translationEvent;
390      protected:
391        /** Number of fragments this request is split into */
392        unsigned int numFragments;
393
394        /** Number of fragments in the address translation mechanism */
395        unsigned int numInTranslationFragments;
396
397        /** Number of fragments that have completed address translation,
398         *  (numTranslatedFragments + numInTranslationFragments) <=
399         *  numFragments.  When numTranslatedFramgents == numFragments,
400         *  translation is complete */
401        unsigned int numTranslatedFragments;
402
403        /** Number of fragments already issued (<= numFragments) */
404        unsigned int numIssuedFragments;
405
406        /** Number of fragments retired back to this request */
407        unsigned int numRetiredFragments;
408
409        /** Fragment Requests corresponding to the address ranges of
410         *  each fragment */
411        std::vector<Request *> fragmentRequests;
412
413        /** Packets matching fragmentRequests to issue fragments to memory */
414        std::vector<Packet *> fragmentPackets;
415
416      protected:
417        /** TLB response interface */
418        void finish(const Fault &fault_, RequestPtr request_,
419                    ThreadContext *tc, BaseTLB::Mode mode);
420
421      public:
422        SplitDataRequest(LSQ &port_, MinorDynInstPtr inst_,
423            bool isLoad_, PacketDataPtr data_ = NULL,
424            uint64_t *res_ = NULL);
425
426        ~SplitDataRequest();
427
428      public:
429        /** Make all the Requests for this transfer's fragments so that those
430         *  requests can be sent for address translation */
431        void makeFragmentRequests();
432
433        /** Make the packets to go with the requests so they can be sent to
434         *  the memory system */
435        void makeFragmentPackets();
436
437        /** Start a loop of do { sendNextFragmentToTranslation ;
438         *  translateTiming ; finish } while (numTranslatedFragments !=
439         *  numFragments) to complete all this requests' fragments' address
440         *  translations */
441        void startAddrTranslation();
442
443        /** Get the head packet as counted by numIssuedFragments */
444        PacketPtr getHeadPacket();
445
446        /** Step on numIssuedFragments */
447        void stepToNextPacket();
448
449        bool hasPacketsInMemSystem()
450        { return numIssuedFragments != numRetiredFragments; }
451
452        /** Have we stepped past the end of fragmentPackets? */
453        bool sentAllPackets() { return numIssuedFragments == numFragments; }
454
455        /** For loads, paste the response data into the main
456         *  response packet */
457        void retireResponse(PacketPtr packet_);
458
459        /** Part of the address translation loop, see startAddTranslation */
460        void sendNextFragmentToTranslation();
461    };
462
463    /** Store buffer.  This contains stores which have been committed
464     *  but whose memory transfers have not yet been issued. Load data
465     *  can be forwarded out of the store buffer */
466    class StoreBuffer : public Named
467    {
468      public:
469        /** My owner */
470        LSQ &lsq;
471
472        /** Number of slots, this is a bound on the size of slots */
473        const unsigned int numSlots;
474
475        /** Maximum number of stores that can be issued per cycle */
476        const unsigned int storeLimitPerCycle;
477
478      public:
479        /** Queue of store requests on their way to memory */
480        std::deque<LSQRequestPtr> slots;
481
482        /** Number of occupied slots which have not yet issued a
483         *  memory access */
484        unsigned int numUnissuedAccesses;
485
486      public:
487        StoreBuffer(std::string name_, LSQ &lsq_,
488            unsigned int store_buffer_size,
489            unsigned int store_limit_per_cycle);
490
491      public:
492        /** Can a new request be inserted into the queue? */
493        bool canInsert() const;
494
495        /** Delete the given request and free the slot it occupied */
496        void deleteRequest(LSQRequestPtr request);
497
498        /** Insert a request at the back of the queue */
499        void insert(LSQRequestPtr request);
500
501        /** Look for a store which satisfies the given load.  Returns an
502         *  indication whether the forwarding request can be wholly,
503         *  partly or not all all satisfied.  If the request can be
504         *  wholly satisfied, the store buffer slot number which can be used
505         *  is returned in found_slot */
506        AddrRangeCoverage canForwardDataToLoad(LSQRequestPtr request,
507            unsigned int &found_slot);
508
509        /** Fill the given packet with appropriate date from slot
510         *  slot_number */
511        void forwardStoreData(LSQRequestPtr load, unsigned int slot_number);
512
513        /** Number of stores in the store buffer which have not been
514         *  completely issued to the memory system */
515        unsigned int numUnissuedStores() { return numUnissuedAccesses; }
516
517        /** Count a store being issued to memory by decrementing
518         *  numUnissuedAccesses.  Does not count barrier requests as they
519         *  will be handles as barriers are cleared from the buffer */
520        void countIssuedStore(LSQRequestPtr request);
521
522        /** Drained if there is absolutely nothing left in the buffer */
523        bool isDrained() const { return slots.empty(); }
524
525        /** Try to issue more stores to memory */
526        void step();
527
528        /** Report queue contents for MinorTrace */
529        void minorTrace() const;
530    };
531
532  protected:
533    /** Most recent execSeqNum of a memory barrier instruction or
534     *  0 if there are no in-flight barriers.  Useful as a
535     *  dependency for early-issued memory operations */
536    InstSeqNum lastMemBarrier;
537
538  public:
539    /** Retry state of last issued memory transfer */
540    MemoryState state;
541
542    /** Maximum number of in-flight accesses issued to the memory system */
543    const unsigned int inMemorySystemLimit;
544
545    /** Memory system access width (and snap) in bytes */
546    const unsigned int lineWidth;
547
548  public:
549    /** The LSQ consists of three queues: requests, transfers and the
550     *  store buffer storeBuffer. */
551
552    typedef Queue<LSQRequestPtr,
553        ReportTraitsPtrAdaptor<LSQRequestPtr>,
554        NoBubbleTraits<LSQRequestPtr> >
555        LSQQueue;
556
557    /** requests contains LSQRequests which have been issued to the TLB by
558     *  calling ExecContext::readMem/writeMem (which in turn calls
559     *  LSQ::pushRequest and LSQRequest::startAddrTranslation).  Once they
560     *  have a physical address, requests at the head of requests can be
561     *  issued to the memory system.  At this stage, it cannot be clear that
562     *  memory accesses *must* happen (that there are no preceding faults or
563     *  changes of flow of control) and so only cacheable reads are issued
564     *  to memory.
565     *  Cacheable stores are not issued at all (and just pass through
566     *  'transfers' in order) and all other transfers are stalled in requests
567     *  until their corresponding instructions are at the head of the
568     *  inMemInsts instruction queue and have the right streamSeqNum. */
569    LSQQueue requests;
570
571    /** Once issued to memory (or, for stores, just had their
572     *  state changed to StoreToStoreBuffer) LSQRequests pass through
573     *  transfers waiting for memory responses.  At the head of transfers,
574     *  Execute::commitInst can pick up the memory response for a request
575     *  using LSQ::findResponse.  Responses to be committed can then
576     *  have ExecContext::completeAcc on them.  Stores can then be pushed
577     *  into the store buffer.  All other transfers will then be complete. */
578    LSQQueue transfers;
579
580    /* The store buffer contains committed cacheable stores on
581     * their way to memory decoupled from subsequence instruction execution.
582     * Before trying to issue a cacheable read from 'requests' to memory,
583     * the store buffer is checked to see if a previous store contains the
584     * needed data (StoreBuffer::canForwardDataToLoad) which can be
585     * forwarded in lieu of a memory access.  If there are outstanding
586     * stores in the transfers queue, they must be promoted to the store
587     * buffer (and so be commited) before they can be correctly checked
588     * for forwarding. */
589    StoreBuffer storeBuffer;
590
591  protected:
592    /** Count of the number of mem. accesses which have left the
593     *  requests queue and are in the 'wild' in the memory system and who
594     *  *must not* be interrupted as they are not normal cacheable
595     *  accesses.  This is a count of the number of in-flight requests
596     *  with issuedToMemory set who have visited tryToSendRequest at least
597     *  once */
598    unsigned int numAccessesInMemorySystem;
599
600    /** Number of requests in the DTLB in the requests queue */
601    unsigned int numAccessesInDTLB;
602
603    /** The number of stores in the transfers queue.  Useful when
604     *  testing if the store buffer contains all the forwardable stores */
605    unsigned int numStoresInTransfers;
606
607    /** The number of accesses which have been issued to the memory
608     *  system but have not been committed/discarded *excluding*
609     *  cacheable normal loads which don't need to be tracked */
610    unsigned int numAccessesIssuedToMemory;
611
612    /** The request (from either requests or the store buffer) which is
613     *  currently waiting have its memory access retried */
614    LSQRequestPtr retryRequest;
615
616    /** Address Mask for a cache block (e.g. ~(cache_block_size-1)) */
617    Addr cacheBlockMask;
618
619  protected:
620    /** Try and issue a memory access for a translated request at the
621     *  head of the requests queue.  Also tries to move the request
622     *  between queues */
623    void tryToSendToTransfers(LSQRequestPtr request);
624
625    /** Try to send (or resend) a memory request's next/only packet to
626     *  the memory system.  Returns true if the request was successfully
627     *  sent to memory (and was also the last packet in a transfer) */
628    bool tryToSend(LSQRequestPtr request);
629
630    /** Clear a barrier (if it's the last one marked up in lastMemBarrier) */
631    void clearMemBarrier(MinorDynInstPtr inst);
632
633    /** Move a request between queues */
634    void moveFromRequestsToTransfers(LSQRequestPtr request);
635
636    /** Can a request be sent to the memory system */
637    bool canSendToMemorySystem();
638
639  public:
640    LSQ(std::string name_, std::string dcache_port_name_,
641        MinorCPU &cpu_, Execute &execute_,
642        unsigned int max_accesses_in_memory_system, unsigned int line_width,
643        unsigned int requests_queue_size, unsigned int transfers_queue_size,
644        unsigned int store_buffer_size,
645        unsigned int store_buffer_cycle_store_limit);
646
647    virtual ~LSQ();
648
649  public:
650    /** Step checks the queues to see if their are issuable transfers
651     *  which were not otherwise picked up by tests at the end of other
652     *  events.
653     *
654     *  Steppable actions include deferred actions which couldn't be
655     *  cascaded on the end of a memory response/TLB response event
656     *  because of resource congestion. */
657    void step();
658
659    /** Is their space in the request queue to be able to push a request by
660     *  issuing an isMemRef instruction */
661    bool canRequest() { return requests.unreservedRemainingSpace() != 0; }
662
663    /** Returns a response if it's at the head of the transfers queue and
664     *  it's either complete or can be sent on to the store buffer.  After
665     *  calling, the request still remains on the transfer queue until
666     *  popResponse is called */
667    LSQRequestPtr findResponse(MinorDynInstPtr inst);
668
669    /** Sanity check and pop the head response */
670    void popResponse(LSQRequestPtr response);
671
672    /** Must check this before trying to insert into the store buffer */
673    bool canPushIntoStoreBuffer() const { return storeBuffer.canInsert(); }
674
675    /** A store has been committed, please move it to the store buffer */
676    void sendStoreToStoreBuffer(LSQRequestPtr request);
677
678    /** Are there any accesses other than normal cached loads in the
679     *  memory system or having received responses which need to be
680     *  handled for their instruction's to be completed */
681    bool accessesInFlight() const
682    { return numAccessesIssuedToMemory != 0; }
683
684    /** A memory barrier instruction has been issued, remember its
685     *  execSeqNum that we can avoid issuing memory ops until it is
686     *  committed */
687    void issuedMemBarrierInst(MinorDynInstPtr inst);
688
689    /** Get the execSeqNum of the last issued memory barrier */
690    InstSeqNum getLastMemBarrier() const { return lastMemBarrier; }
691
692    /** Is there nothing left in the LSQ */
693    bool isDrained();
694
695    /** May need to be ticked next cycle as one of the queues contains
696     *  an actionable transfers or address translation */
697    bool needsToTick();
698
699    /** Complete a barrier instruction.  Where committed, makes a
700     *  BarrierDataRequest and pushed it into the store buffer */
701    void completeMemBarrierInst(MinorDynInstPtr inst,
702        bool committed);
703
704    /** Single interface for readMem/writeMem to issue requests into
705     *  the LSQ */
706    void pushRequest(MinorDynInstPtr inst, bool isLoad, uint8_t *data,
707        unsigned int size, Addr addr, unsigned int flags, uint64_t *res);
708
709    /** Push a predicate failed-representing request into the queues just
710     *  to maintain commit order */
711    void pushFailedRequest(MinorDynInstPtr inst);
712
713    /** Memory interface */
714    bool recvTimingResp(PacketPtr pkt);
715    void recvReqRetry();
716    void recvTimingSnoopReq(PacketPtr pkt);
717
718    /** Return the raw-bindable port */
719    MinorCPU::MinorCPUPort &getDcachePort() { return dcachePort; }
720
721    void minorTrace() const;
722};
723
724/** Make a suitable packet for the given request.  If the request is a store,
725 *  data will be the payload data.  If sender_state is NULL, it won't be
726 *  pushed into the packet as senderState */
727PacketPtr makePacketForRequest(Request &request, bool isLoad,
728    Packet::SenderState *sender_state = NULL, PacketDataPtr data = NULL);
729}
730
731#endif /* __CPU_MINOR_NEW_LSQ_HH__ */
732