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 recvReqRetry() { fetch.recvReqRetry(); }
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        RequestPtr 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_, const 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            request = std::make_shared<Request>();
181        }
182
183        ~FetchRequest();
184    };
185
186    typedef FetchRequest *FetchRequestPtr;
187
188  protected:
189    /** Construction-assigned data members */
190
191    /** Pointer back to the containing CPU */
192    MinorCPU &cpu;
193
194    /** Input port carrying branch requests from Execute */
195    Latch<BranchData>::Output inp;
196    /** Output port carrying read lines to Fetch2 */
197    Latch<ForwardLineData>::Input out;
198    /** Input port carrying branch predictions from Fetch2 */
199    Latch<BranchData>::Output prediction;
200
201    /** Interface to reserve space in the next stage */
202    std::vector<InputBuffer<ForwardLineData>> &nextStageReserve;
203
204    /** IcachePort to pass to the CPU.  Fetch1 is the only module that uses
205     *  it. */
206    IcachePort icachePort;
207
208    /** Line snap size in bytes.  All fetches clip to make their ends not
209     *  extend beyond this limit.  Setting this to the machine L1 cache line
210     *  length will result in fetches never crossing line boundaries. */
211    unsigned int lineSnap;
212
213    /** Maximum fetch width in bytes.  Setting this (and lineSnap) to the
214     *  machine L1 cache line length will result in fetches of whole cache
215     *  lines.  Setting this to sizeof(MachInst) will result it fetches of
216     *  single instructions (except near the end of lineSnap lines) */
217    unsigned int maxLineWidth;
218
219    /** Maximum number of fetches allowed in flight (in queues or memory) */
220    unsigned int fetchLimit;
221
222  protected:
223    /** Cycle-by-cycle state */
224
225    /** State of memory access for head instruction fetch */
226    enum FetchState
227    {
228        FetchHalted, /* Not fetching, waiting to be woken by transition
229            to FetchWaitingForPC.  The PC is not valid in this state */
230        FetchWaitingForPC, /* Not fetching, waiting for stream change.
231            This doesn't stop issued fetches from being returned and
232            processed or for branches to change the state to Running. */
233        FetchRunning /* Try to fetch, when possible */
234    };
235
236    /** Stage cycle-by-cycle state */
237
238    struct Fetch1ThreadInfo {
239
240        /** Consturctor to initialize all fields. */
241        Fetch1ThreadInfo() :
242            state(FetchWaitingForPC),
243            pc(TheISA::PCState(0)),
244            streamSeqNum(InstId::firstStreamSeqNum),
245            predictionSeqNum(InstId::firstPredictionSeqNum),
246            blocked(false),
247            wakeupGuard(false)
248        { }
249
250        Fetch1ThreadInfo(const Fetch1ThreadInfo& other) :
251            state(other.state),
252            pc(other.pc),
253            streamSeqNum(other.streamSeqNum),
254            predictionSeqNum(other.predictionSeqNum),
255            blocked(other.blocked)
256        { }
257
258        FetchState state;
259
260        /** Fetch PC value. This is updated by branches from Execute, branch
261         *  prediction targets from Fetch2 and by incrementing it as we fetch
262         *  lines subsequent to those two sources. */
263        TheISA::PCState pc;
264
265        /** Stream sequence number.  This changes on request from Execute and is
266         *  used to tag instructions by the fetch stream to which they belong.
267         *  Execute originates new prediction sequence numbers. */
268        InstSeqNum streamSeqNum;
269
270        /** Prediction sequence number.  This changes when requests from Execute
271         *  or Fetch2 ask for a change of fetch address and is used to tag lines
272         *  by the prediction to which they belong.  Fetch2 originates
273         *  prediction sequence numbers. */
274        InstSeqNum predictionSeqNum;
275
276        /** Blocked indication for report */
277        bool blocked;
278
279        /** Signal to guard against sleeping first cycle of wakeup */
280        bool wakeupGuard;
281    };
282
283    std::vector<Fetch1ThreadInfo> fetchInfo;
284    ThreadID threadPriority;
285
286    /** State of memory access for head instruction fetch */
287    enum IcacheState
288    {
289        IcacheRunning, /* Default. Step icache queues when possible */
290        IcacheNeedsRetry /* Request rejected, will be asked to retry */
291    };
292
293    typedef Queue<FetchRequestPtr,
294        ReportTraitsPtrAdaptor<FetchRequestPtr>,
295        NoBubbleTraits<FetchRequestPtr> >
296        FetchQueue;
297
298    /** Queue of address translated requests from Fetch1 */
299    FetchQueue requests;
300
301    /** Queue of in-memory system requests and responses */
302    FetchQueue transfers;
303
304    /** Retry state of icache_port */
305    IcacheState icacheState;
306
307    /** Sequence number for line fetch used for ordering lines to flush */
308    InstSeqNum lineSeqNum;
309
310    /** Count of the number fetches which have left the transfers queue
311     *  and are in the 'wild' in the memory system.  Try not to rely on
312     *  this value, it's better to code without knowledge of the number
313     *  of outstanding accesses */
314    unsigned int numFetchesInMemorySystem;
315    /** Number of requests inside the ITLB rather than in the queues.
316     *  All requests so located *must* have reserved space in the
317     *  transfers queue */
318    unsigned int numFetchesInITLB;
319
320  protected:
321    friend std::ostream &operator <<(std::ostream &os,
322        Fetch1::FetchState state);
323
324    /** Start fetching from a new address. */
325    void changeStream(const BranchData &branch);
326
327    /** Update streamSeqNum and predictionSeqNum from the given branch (and
328     *  assume these have changed and discard (on delivery) all lines in
329     *  flight) */
330    void updateExpectedSeqNums(const BranchData &branch);
331
332    /** Convert a response to a ForwardLineData */
333    void processResponse(FetchRequestPtr response,
334        ForwardLineData &line);
335
336    friend std::ostream &operator <<(std::ostream &os,
337        IcacheState state);
338
339
340    /** Use the current threading policy to determine the next thread to
341     *  fetch from. */
342    ThreadID getScheduledThread();
343
344    /** Insert a line fetch into the requests.  This can be a partial
345     *  line request where the given address has a non-0 offset into a
346     *  line. */
347    void fetchLine(ThreadID tid);
348
349    /** Try and issue a fetch for a translated request at the
350     *  head of the requests queue.  Also tries to move the request
351     *  between queues */
352    void tryToSendToTransfers(FetchRequestPtr request);
353
354    /** Try to send (or resend) a memory request's next/only packet to
355     *  the memory system.  Returns true if the fetch was successfully
356     *  sent to memory */
357    bool tryToSend(FetchRequestPtr request);
358
359    /** Move a request between queues */
360    void moveFromRequestsToTransfers(FetchRequestPtr request);
361
362    /** Step requests along between requests and transfers queues */
363    void stepQueues();
364
365    /** Pop a request from the given queue and correctly deallocate and
366     *  discard it. */
367    void popAndDiscard(FetchQueue &queue);
368
369    /** Handle pushing a TLB response onto the right queue */
370    void handleTLBResponse(FetchRequestPtr response);
371
372    /** Returns the total number of queue occupancy, in-ITLB and
373     *  in-memory system fetches */
374    unsigned int numInFlightFetches();
375
376    /** Print the appropriate MinorLine line for a fetch response */
377    void minorTraceResponseLine(const std::string &name,
378        FetchRequestPtr response) const;
379
380    /** Memory interface */
381    virtual bool recvTimingResp(PacketPtr pkt);
382    virtual void recvReqRetry();
383
384  public:
385    Fetch1(const std::string &name_,
386        MinorCPU &cpu_,
387        MinorCPUParams &params,
388        Latch<BranchData>::Output inp_,
389        Latch<ForwardLineData>::Input out_,
390        Latch<BranchData>::Output prediction_,
391        std::vector<InputBuffer<ForwardLineData>> &next_stage_input_buffer);
392
393  public:
394    /** Returns the IcachePort owned by this Fetch1 */
395    MinorCPU::MinorCPUPort &getIcachePort() { return icachePort; }
396
397    /** Pass on input/buffer data to the output if you can */
398    void evaluate();
399
400    /** Initiate fetch1 fetching */
401    void wakeupFetch(ThreadID tid);
402
403    void minorTrace() const;
404
405    /** Is this stage drained?  For Fetch1, draining is initiated by
406     *  Execute signalling a branch with the reason HaltFetch */
407    bool isDrained();
408};
409
410}
411
412#endif /* __CPU_MINOR_FETCH1_HH__ */
413