fetch1.hh revision 10379:c00f6d7e2681
1/*
2 * Copyright (c) 2013-2014 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Andrew Bardsley
38 */
39
40/**
41 * @file
42 *
43 *  Fetch1 is responsible for fetching "lines" from memory and passing
44 *  them to Fetch2
45 */
46
47#ifndef __CPU_MINOR_FETCH1_HH__
48#define __CPU_MINOR_FETCH1_HH__
49
50#include "cpu/minor/buffers.hh"
51#include "cpu/minor/cpu.hh"
52#include "cpu/minor/pipe_data.hh"
53#include "cpu/base.hh"
54#include "mem/packet.hh"
55
56namespace Minor
57{
58
59/** A stage responsible for fetching "lines" from memory and passing
60 *  them to Fetch2 */
61class Fetch1 : public Named
62{
63  protected:
64    /** Exposable fetch port */
65    class IcachePort : public MinorCPU::MinorCPUPort
66    {
67      protected:
68        /** My owner */
69        Fetch1 &fetch;
70
71      public:
72        IcachePort(std::string name, Fetch1 &fetch_, MinorCPU &cpu) :
73            MinorCPU::MinorCPUPort(name, cpu), fetch(fetch_)
74        { }
75
76      protected:
77        bool recvTimingResp(PacketPtr pkt)
78        { return fetch.recvTimingResp(pkt); }
79
80        void recvRetry() { fetch.recvRetry(); }
81    };
82
83    /** Memory access queuing.
84     *
85     *  A request can be submitted by pushing it onto the requests queue after
86     *  issuing an ITLB lookup (state becomes InTranslation) with a
87     *  FetchSenderState senderState containing the current lineSeqNum and
88     *  stream/predictionSeqNum.
89     *
90     *  Translated packets (state becomes Translation) are then passed to the
91     *  memory system and the transfers queue (state becomes RequestIssuing).
92     *  Retries are handled by leaving the packet on the requests queue and
93     *  changing the state to IcacheNeedsRetry).
94     *
95     *  Responses from the memory system alter the request object (state
96     *  become Complete).  Responses can be picked up from the head of the
97     *  transfers queue to pass on to Fetch2. */
98
99    /** Structure to hold SenderState info through
100     *  translation and memory accesses. */
101    class FetchRequest :
102        public BaseTLB::Translation, /* For TLB lookups */
103        public Packet::SenderState /* For packing into a Packet */
104    {
105      protected:
106        /** Owning fetch unit */
107        Fetch1 &fetch;
108
109      public:
110        /** Progress of this request through address translation and
111         *  memory */
112        enum FetchRequestState
113        {
114            NotIssued, /* Just been made */
115            InTranslation, /* Issued to ITLB, must wait for reqply */
116            Translated, /* Translation complete */
117            RequestIssuing, /* Issued to memory, must wait for response */
118            Complete /* Complete.  Either a fault, or a fetched line */
119        };
120
121        FetchRequestState state;
122
123        /** Identity of the line that this request will generate */
124        InstId id;
125
126        /** FetchRequests carry packets while they're in the requests and
127         * transfers responses queues.  When a Packet returns from the memory
128         * system, its request needs to have its packet updated as this may
129         * have changed in flight */
130        PacketPtr packet;
131
132        /** The underlying request that this fetch represents */
133        Request request;
134
135        /** PC to fixup with line address */
136        TheISA::PCState pc;
137
138        /** Fill in a fault if one happens during fetch, check this by
139         *  picking apart the response packet */
140        Fault fault;
141
142        /** Make a packet to use with the memory transaction */
143        void makePacket();
144
145        /** Report interface */
146        void reportData(std::ostream &os) const;
147
148        /** Is this line out of date with the current stream/prediction
149         *  sequence and can it be discarded without orphaning in flight
150         *  TLB lookups/memory accesses? */
151        bool isDiscardable() const;
152
153        /** Is this a complete read line or fault */
154        bool isComplete() const { return state == Complete; }
155
156      protected:
157        /** BaseTLB::Translation interface */
158
159        /** Interface for ITLB responses.  We can handle delay, so don't
160         *  do anything */
161        void markDelayed() { }
162
163        /** Interface for ITLB responses.  Populates self and then passes
164         *  the request on to the ports' handleTLBResponse member
165         *  function */
166        void finish(const Fault &fault_, RequestPtr request_,
167                    ThreadContext *tc, BaseTLB::Mode mode);
168
169      public:
170        FetchRequest(Fetch1 &fetch_, InstId id_, TheISA::PCState pc_) :
171            SenderState(),
172            fetch(fetch_),
173            state(NotIssued),
174            id(id_),
175            packet(NULL),
176            request(),
177            pc(pc_),
178            fault(NoFault)
179        { }
180
181        ~FetchRequest();
182    };
183
184    typedef FetchRequest *FetchRequestPtr;
185
186  protected:
187    /** Construction-assigned data members */
188
189    /** Pointer back to the containing CPU */
190    MinorCPU &cpu;
191
192    /** Input port carrying branch requests from Execute */
193    Latch<BranchData>::Output inp;
194    /** Output port carrying read lines to Fetch2 */
195    Latch<ForwardLineData>::Input out;
196    /** Input port carrying branch predictions from Fetch2 */
197    Latch<BranchData>::Output prediction;
198
199    /** Interface to reserve space in the next stage */
200    Reservable &nextStageReserve;
201
202    /** IcachePort to pass to the CPU.  Fetch1 is the only module that uses
203     *  it. */
204    IcachePort icachePort;
205
206    /** Line snap size in bytes.  All fetches clip to make their ends not
207     *  extend beyond this limit.  Setting this to the machine L1 cache line
208     *  length will result in fetches never crossing line boundaries. */
209    unsigned int lineSnap;
210
211    /** Maximum fetch width in bytes.  Setting this (and lineSnap) to the
212     *  machine L1 cache line length will result in fetches of whole cache
213     *  lines.  Setting this to sizeof(MachInst) will result it fetches of
214     *  single instructions (except near the end of lineSnap lines) */
215    unsigned int maxLineWidth;
216
217    /** Maximum number of fetches allowed in flight (in queues or memory) */
218    unsigned int fetchLimit;
219
220  protected:
221    /** Cycle-by-cycle state */
222
223    /** State of memory access for head instruction fetch */
224    enum FetchState
225    {
226        FetchHalted, /* Not fetching, waiting to be woken by transition
227            to FetchWaitingForPC.  The PC is not valid in this state */
228        FetchWaitingForPC, /* Not fetching, waiting for stream change.
229            This doesn't stop issued fetches from being returned and
230            processed or for branches to change the state to Running. */
231        FetchRunning /* Try to fetch, when possible */
232    };
233
234    /** Stage cycle-by-cycle state */
235
236    FetchState state;
237
238    /** Fetch PC value. This is updated by branches from Execute, branch
239     *  prediction targets from Fetch2 and by incrementing it as we fetch
240     *  lines subsequent to those two sources. */
241    TheISA::PCState pc;
242
243    /** Stream sequence number.  This changes on request from Execute and is
244     *  used to tag instructions by the fetch stream to which they belong.
245     *  Execute originates new prediction sequence numbers. */
246    InstSeqNum streamSeqNum;
247
248    /** Prediction sequence number.  This changes when requests from Execute
249     *  or Fetch2 ask for a change of fetch address and is used to tag lines
250     *  by the prediction to which they belong.  Fetch2 originates
251     *  prediction sequence numbers. */
252    InstSeqNum predictionSeqNum;
253
254    /** The sequence number expected for the next returned cache line.  The
255     *  responses queue should be ordered and so, if the front of that queue
256     *  has a lower lineSeqNum than this, lines need to be discarded.  If it
257     *  has a higher lineSeqNum, our line hasn't appeared yet */
258    InstSeqNum expectedLineSeqNum;
259
260    /** Blocked indication for report */
261    bool blocked;
262
263    /** State of memory access for head instruction fetch */
264    enum IcacheState
265    {
266        IcacheRunning, /* Default. Step icache queues when possible */
267        IcacheNeedsRetry /* Request rejected, will be asked to retry */
268    };
269
270    typedef Queue<FetchRequestPtr,
271        ReportTraitsPtrAdaptor<FetchRequestPtr>,
272        NoBubbleTraits<FetchRequestPtr> >
273        FetchQueue;
274
275    /** Queue of address translated requests from Fetch1 */
276    FetchQueue requests;
277
278    /** Queue of in-memory system requests and responses */
279    FetchQueue transfers;
280
281    /** Retry state of icache_port */
282    IcacheState icacheState;
283
284    /** Sequence number for line fetch used for ordering lines to flush */
285    InstSeqNum lineSeqNum;
286
287    /** Count of the number fetches which have left the transfers queue
288     *  and are in the 'wild' in the memory system.  Try not to rely on
289     *  this value, it's better to code without knowledge of the number
290     *  of outstanding accesses */
291    unsigned int numFetchesInMemorySystem;
292    /** Number of requests inside the ITLB rather than in the queues.
293     *  All requests so located *must* have reserved space in the
294     *  transfers queue */
295    unsigned int numFetchesInITLB;
296
297  protected:
298    friend std::ostream &operator <<(std::ostream &os,
299        Fetch1::FetchState state);
300
301    /** Start fetching from a new address. */
302    void changeStream(const BranchData &branch);
303
304    /** Update streamSeqNum and predictionSeqNum from the given branch (and
305     *  assume these have changed and discard (on delivery) all lines in
306     *  flight) */
307    void updateExpectedSeqNums(const BranchData &branch);
308
309    /** Convert a response to a ForwardLineData */
310    void processResponse(FetchRequestPtr response,
311        ForwardLineData &line);
312
313    friend std::ostream &operator <<(std::ostream &os,
314        IcacheState state);
315
316    /** Insert a line fetch into the requests.  This can be a partial
317     *  line request where the given address has a non-0 offset into a
318     *  line. */
319    void fetchLine();
320
321    /** Try and issue a fetch for a translated request at the
322     *  head of the requests queue.  Also tries to move the request
323     *  between queues */
324    void tryToSendToTransfers(FetchRequestPtr request);
325
326    /** Try to send (or resend) a memory request's next/only packet to
327     *  the memory system.  Returns true if the fetch was successfully
328     *  sent to memory */
329    bool tryToSend(FetchRequestPtr request);
330
331    /** Move a request between queues */
332    void moveFromRequestsToTransfers(FetchRequestPtr request);
333
334    /** Step requests along between requests and transfers queues */
335    void stepQueues();
336
337    /** Pop a request from the given queue and correctly deallocate and
338     *  discard it. */
339    void popAndDiscard(FetchQueue &queue);
340
341    /** Handle pushing a TLB response onto the right queue */
342    void handleTLBResponse(FetchRequestPtr response);
343
344    /** Returns the total number of queue occupancy, in-ITLB and
345     *  in-memory system fetches */
346    unsigned int numInFlightFetches();
347
348    /** Print the appropriate MinorLine line for a fetch response */
349    void minorTraceResponseLine(const std::string &name,
350        FetchRequestPtr response) const;
351
352    /** Memory interface */
353    virtual bool recvTimingResp(PacketPtr pkt);
354    virtual void recvRetry();
355
356  public:
357    Fetch1(const std::string &name_,
358        MinorCPU &cpu_,
359        MinorCPUParams &params,
360        Latch<BranchData>::Output inp_,
361        Latch<ForwardLineData>::Input out_,
362        Latch<BranchData>::Output prediction_,
363        Reservable &next_stage_input_buffer);
364
365  public:
366    /** Returns the IcachePort owned by this Fetch1 */
367    MinorCPU::MinorCPUPort &getIcachePort() { return icachePort; }
368
369    /** Pass on input/buffer data to the output if you can */
370    void evaluate();
371
372    void minorTrace() const;
373
374    /** Is this stage drained?  For Fetch1, draining is initiated by
375     *  Execute signalling a branch with the reason HaltFetch */
376    bool isDrained();
377};
378
379}
380
381#endif /* __CPU_MINOR_FETCH1_HH__ */
382