lsq.hh (10713:eddb533708cb) lsq.hh (11331:cd5c48db28e6)
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 * A load/store queue that allows outstanding reads and writes.
44 *
45 */
46
47#ifndef __CPU_MINOR_NEW_LSQ_HH__
48#define __CPU_MINOR_NEW_LSQ_HH__
49
50#include "cpu/minor/buffers.hh"
51#include "cpu/minor/cpu.hh"
52#include "cpu/minor/pipe_data.hh"
53#include "cpu/minor/trace.hh"
54
55namespace Minor
56{
57
58/* Forward declaration */
59class Execute;
60
61class LSQ : public Named
62{
63 protected:
64 /** My owner(s) */
65 MinorCPU &cpu;
66 Execute &execute;
67
68 protected:
69 /** State of memory access for head access. */
70 enum MemoryState
71 {
72 MemoryRunning, /* Default. Step dcache queues when possible. */
73 MemoryNeedsRetry /* Request rejected, will be asked to retry */
74 };
75
76 /** Print MemoryState values as shown in the enum definition */
77 friend std::ostream &operator <<(std::ostream &os,
78 MemoryState state);
79
80 /** Coverage of one address range with another */
81 enum AddrRangeCoverage
82 {
83 PartialAddrRangeCoverage, /* Two ranges partly overlap */
84 FullAddrRangeCoverage, /* One range fully covers another */
85 NoAddrRangeCoverage /* Two ranges are disjoint */
86 };
87
88 /** Exposable data port */
89 class DcachePort : public MinorCPU::MinorCPUPort
90 {
91 protected:
92 /** My owner */
93 LSQ &lsq;
94
95 public:
96 DcachePort(std::string name, LSQ &lsq_, MinorCPU &cpu) :
97 MinorCPU::MinorCPUPort(name, cpu), lsq(lsq_)
98 { }
99
100 protected:
101 bool recvTimingResp(PacketPtr pkt)
102 { return lsq.recvTimingResp(pkt); }
103
104 void recvReqRetry() { lsq.recvReqRetry(); }
105
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 * A load/store queue that allows outstanding reads and writes.
44 *
45 */
46
47#ifndef __CPU_MINOR_NEW_LSQ_HH__
48#define __CPU_MINOR_NEW_LSQ_HH__
49
50#include "cpu/minor/buffers.hh"
51#include "cpu/minor/cpu.hh"
52#include "cpu/minor/pipe_data.hh"
53#include "cpu/minor/trace.hh"
54
55namespace Minor
56{
57
58/* Forward declaration */
59class Execute;
60
61class LSQ : public Named
62{
63 protected:
64 /** My owner(s) */
65 MinorCPU &cpu;
66 Execute &execute;
67
68 protected:
69 /** State of memory access for head access. */
70 enum MemoryState
71 {
72 MemoryRunning, /* Default. Step dcache queues when possible. */
73 MemoryNeedsRetry /* Request rejected, will be asked to retry */
74 };
75
76 /** Print MemoryState values as shown in the enum definition */
77 friend std::ostream &operator <<(std::ostream &os,
78 MemoryState state);
79
80 /** Coverage of one address range with another */
81 enum AddrRangeCoverage
82 {
83 PartialAddrRangeCoverage, /* Two ranges partly overlap */
84 FullAddrRangeCoverage, /* One range fully covers another */
85 NoAddrRangeCoverage /* Two ranges are disjoint */
86 };
87
88 /** Exposable data port */
89 class DcachePort : public MinorCPU::MinorCPUPort
90 {
91 protected:
92 /** My owner */
93 LSQ &lsq;
94
95 public:
96 DcachePort(std::string name, LSQ &lsq_, MinorCPU &cpu) :
97 MinorCPU::MinorCPUPort(name, cpu), lsq(lsq_)
98 { }
99
100 protected:
101 bool recvTimingResp(PacketPtr pkt)
102 { return lsq.recvTimingResp(pkt); }
103
104 void recvReqRetry() { lsq.recvReqRetry(); }
105
106 bool isSnooping() const override { return true; }
107
106 void recvTimingSnoopReq(PacketPtr pkt)
107 { return lsq.recvTimingSnoopReq(pkt); }
108 void recvTimingSnoopReq(PacketPtr pkt)
109 { return lsq.recvTimingSnoopReq(pkt); }
110
111 void recvFunctionalSnoop(PacketPtr pkt) { }
108 };
109
110 DcachePort dcachePort;
111
112 public:
113 /** Derived SenderState to carry data access info. through address
114 * translation, the queues in this port and back from the memory
115 * system. */
116 class LSQRequest :
117 public BaseTLB::Translation, /* For TLB lookups */
118 public Packet::SenderState /* For packing into a Packet */
119 {
120 public:
121 /** Owning port */
122 LSQ &port;
123
124 /** Instruction which made this request */
125 MinorDynInstPtr inst;
126
127 /** Load/store indication used for building packet. This isn't
128 * carried by Request so we need to keep it here */
129 bool isLoad;
130
131 /** Dynamically allocated and populated data carried for
132 * building write packets */
133 PacketDataPtr data;
134
135 /* Requests carry packets on their way to the memory system.
136 * When a Packet returns from the memory system, its
137 * request needs to have its packet updated as this
138 * may have changed in flight */
139 PacketPtr packet;
140
141 /** The underlying request of this LSQRequest */
142 Request request;
143
144 /** Fault generated performing this request */
145 Fault fault;
146
147 /** Res from pushRequest */
148 uint64_t *res;
149
150 /** Was skipped. Set to indicate any reason (faulted, bad
151 * stream sequence number, in a fault shadow) that this
152 * request did not perform a memory transfer */
153 bool skipped;
154
155 /** This in an access other than a normal cacheable load
156 * that's visited the memory system */
157 bool issuedToMemory;
158
159 enum LSQRequestState
160 {
161 NotIssued, /* Newly created */
162 InTranslation, /* TLB accessed, no reply yet */
163 Translated, /* Finished address translation */
164 Failed, /* The starting start of FailedDataRequests */
165 RequestIssuing, /* Load/store issued to memory in the requests
166 queue */
167 StoreToStoreBuffer, /* Store in transfers on its way to the
168 store buffer */
169 RequestNeedsRetry, /* Retry needed for load */
170 StoreInStoreBuffer, /* Store in the store buffer, before issuing
171 a memory transfer */
172 StoreBufferIssuing, /* Store in store buffer and has been
173 issued */
174 StoreBufferNeedsRetry, /* Retry needed for store */
175 /* All completed states. Includes
176 completed loads, TLB faults and skipped requests whose
177 seqNum's no longer match */
178 Complete
179 };
180
181 LSQRequestState state;
182
183 protected:
184 /** BaseTLB::Translation interface */
185 void markDelayed() { }
186
187 public:
188 LSQRequest(LSQ &port_, MinorDynInstPtr inst_, bool isLoad_,
189 PacketDataPtr data_ = NULL, uint64_t *res_ = NULL);
190
191 virtual ~LSQRequest();
192
193 public:
194 /** Make a packet to use with the memory transaction */
195 void makePacket();
196
197 /** Was no memory access attempted for this request? */
198 bool skippedMemAccess() { return skipped; }
199
200 /** Set this request as having been skipped before a memory
201 * transfer was attempt */
202 void setSkipped() { skipped = true; }
203
204 /** Does address range req1 (req1_addr to req1_addr + req1_size - 1)
205 * fully cover, partially cover or not cover at all the range req2 */
206 static AddrRangeCoverage containsAddrRangeOf(
207 Addr req1_addr, unsigned int req1_size,
208 Addr req2_addr, unsigned int req2_size);
209
210 /** Does this request's address range fully cover the range
211 * of other_request? */
212 AddrRangeCoverage containsAddrRangeOf(LSQRequest *other_request);
213
214 /** Start the address translation process for this request. This
215 * will issue a translation request to the TLB. */
216 virtual void startAddrTranslation() = 0;
217
218 /** Get the next packet to issue for this request. For split
219 * transfers, it will be necessary to step through the available
220 * packets by calling do { getHeadPacket ; stepToNextPacket } while
221 * (!sentAllPackets) and by retiring response using retireResponse */
222 virtual PacketPtr getHeadPacket() = 0;
223
224 /** Step to the next packet for the next call to getHeadPacket */
225 virtual void stepToNextPacket() = 0;
226
227 /** Have all packets been sent? */
228 virtual bool sentAllPackets() = 0;
229
230 /** True if this request has any issued packets in the memory
231 * system and so can't be interrupted until it gets responses */
232 virtual bool hasPacketsInMemSystem() = 0;
233
234 /** Retire a response packet into the LSQRequest packet possibly
235 * completing this transfer */
236 virtual void retireResponse(PacketPtr packet_) = 0;
237
238 /** Is this a request a barrier? */
239 virtual bool isBarrier();
240
241 /** This request, once processed by the requests/transfers
242 * queues, will need to go to the store buffer */
243 bool needsToBeSentToStoreBuffer();
244
245 /** Set state and output trace output */
246 void setState(LSQRequestState new_state);
247
248 /** Has this request been completed. This includes *all* reasons
249 * for completion: successful transfers, faults, skipped because
250 * of preceding faults */
251 bool isComplete() const;
252
253 /** MinorTrace report interface */
254 void reportData(std::ostream &os) const;
255 };
256
257 typedef LSQRequest *LSQRequestPtr;
258
259 friend std::ostream & operator <<(std::ostream &os,
260 AddrRangeCoverage state);
261
262 friend std::ostream & operator <<(std::ostream &os,
263 LSQRequest::LSQRequestState state);
264
265 protected:
266 /** Special request types that don't actually issue memory requests */
267 class SpecialDataRequest : public LSQRequest
268 {
269 protected:
270 /** TLB interace */
271 void finish(const Fault &fault_, RequestPtr request_,
272 ThreadContext *tc, BaseTLB::Mode mode)
273 { }
274
275 public:
276 /** Send single translation request */
277 void startAddrTranslation() { }
278
279 /** Get the head packet as counted by numIssuedFragments */
280 PacketPtr getHeadPacket()
281 { fatal("No packets in a SpecialDataRequest"); }
282
283 /** Step on numIssuedFragments */
284 void stepToNextPacket() { }
285
286 /** Has no packets to send */
287 bool sentAllPackets() { return true; }
288
289 /** Never sends any requests */
290 bool hasPacketsInMemSystem() { return false; }
291
292 /** Keep the given packet as the response packet
293 * LSQRequest::packet */
294 void retireResponse(PacketPtr packet_) { }
295
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__ */
112 };
113
114 DcachePort dcachePort;
115
116 public:
117 /** Derived SenderState to carry data access info. through address
118 * translation, the queues in this port and back from the memory
119 * system. */
120 class LSQRequest :
121 public BaseTLB::Translation, /* For TLB lookups */
122 public Packet::SenderState /* For packing into a Packet */
123 {
124 public:
125 /** Owning port */
126 LSQ &port;
127
128 /** Instruction which made this request */
129 MinorDynInstPtr inst;
130
131 /** Load/store indication used for building packet. This isn't
132 * carried by Request so we need to keep it here */
133 bool isLoad;
134
135 /** Dynamically allocated and populated data carried for
136 * building write packets */
137 PacketDataPtr data;
138
139 /* Requests carry packets on their way to the memory system.
140 * When a Packet returns from the memory system, its
141 * request needs to have its packet updated as this
142 * may have changed in flight */
143 PacketPtr packet;
144
145 /** The underlying request of this LSQRequest */
146 Request request;
147
148 /** Fault generated performing this request */
149 Fault fault;
150
151 /** Res from pushRequest */
152 uint64_t *res;
153
154 /** Was skipped. Set to indicate any reason (faulted, bad
155 * stream sequence number, in a fault shadow) that this
156 * request did not perform a memory transfer */
157 bool skipped;
158
159 /** This in an access other than a normal cacheable load
160 * that's visited the memory system */
161 bool issuedToMemory;
162
163 enum LSQRequestState
164 {
165 NotIssued, /* Newly created */
166 InTranslation, /* TLB accessed, no reply yet */
167 Translated, /* Finished address translation */
168 Failed, /* The starting start of FailedDataRequests */
169 RequestIssuing, /* Load/store issued to memory in the requests
170 queue */
171 StoreToStoreBuffer, /* Store in transfers on its way to the
172 store buffer */
173 RequestNeedsRetry, /* Retry needed for load */
174 StoreInStoreBuffer, /* Store in the store buffer, before issuing
175 a memory transfer */
176 StoreBufferIssuing, /* Store in store buffer and has been
177 issued */
178 StoreBufferNeedsRetry, /* Retry needed for store */
179 /* All completed states. Includes
180 completed loads, TLB faults and skipped requests whose
181 seqNum's no longer match */
182 Complete
183 };
184
185 LSQRequestState state;
186
187 protected:
188 /** BaseTLB::Translation interface */
189 void markDelayed() { }
190
191 public:
192 LSQRequest(LSQ &port_, MinorDynInstPtr inst_, bool isLoad_,
193 PacketDataPtr data_ = NULL, uint64_t *res_ = NULL);
194
195 virtual ~LSQRequest();
196
197 public:
198 /** Make a packet to use with the memory transaction */
199 void makePacket();
200
201 /** Was no memory access attempted for this request? */
202 bool skippedMemAccess() { return skipped; }
203
204 /** Set this request as having been skipped before a memory
205 * transfer was attempt */
206 void setSkipped() { skipped = true; }
207
208 /** Does address range req1 (req1_addr to req1_addr + req1_size - 1)
209 * fully cover, partially cover or not cover at all the range req2 */
210 static AddrRangeCoverage containsAddrRangeOf(
211 Addr req1_addr, unsigned int req1_size,
212 Addr req2_addr, unsigned int req2_size);
213
214 /** Does this request's address range fully cover the range
215 * of other_request? */
216 AddrRangeCoverage containsAddrRangeOf(LSQRequest *other_request);
217
218 /** Start the address translation process for this request. This
219 * will issue a translation request to the TLB. */
220 virtual void startAddrTranslation() = 0;
221
222 /** Get the next packet to issue for this request. For split
223 * transfers, it will be necessary to step through the available
224 * packets by calling do { getHeadPacket ; stepToNextPacket } while
225 * (!sentAllPackets) and by retiring response using retireResponse */
226 virtual PacketPtr getHeadPacket() = 0;
227
228 /** Step to the next packet for the next call to getHeadPacket */
229 virtual void stepToNextPacket() = 0;
230
231 /** Have all packets been sent? */
232 virtual bool sentAllPackets() = 0;
233
234 /** True if this request has any issued packets in the memory
235 * system and so can't be interrupted until it gets responses */
236 virtual bool hasPacketsInMemSystem() = 0;
237
238 /** Retire a response packet into the LSQRequest packet possibly
239 * completing this transfer */
240 virtual void retireResponse(PacketPtr packet_) = 0;
241
242 /** Is this a request a barrier? */
243 virtual bool isBarrier();
244
245 /** This request, once processed by the requests/transfers
246 * queues, will need to go to the store buffer */
247 bool needsToBeSentToStoreBuffer();
248
249 /** Set state and output trace output */
250 void setState(LSQRequestState new_state);
251
252 /** Has this request been completed. This includes *all* reasons
253 * for completion: successful transfers, faults, skipped because
254 * of preceding faults */
255 bool isComplete() const;
256
257 /** MinorTrace report interface */
258 void reportData(std::ostream &os) const;
259 };
260
261 typedef LSQRequest *LSQRequestPtr;
262
263 friend std::ostream & operator <<(std::ostream &os,
264 AddrRangeCoverage state);
265
266 friend std::ostream & operator <<(std::ostream &os,
267 LSQRequest::LSQRequestState state);
268
269 protected:
270 /** Special request types that don't actually issue memory requests */
271 class SpecialDataRequest : public LSQRequest
272 {
273 protected:
274 /** TLB interace */
275 void finish(const Fault &fault_, RequestPtr request_,
276 ThreadContext *tc, BaseTLB::Mode mode)
277 { }
278
279 public:
280 /** Send single translation request */
281 void startAddrTranslation() { }
282
283 /** Get the head packet as counted by numIssuedFragments */
284 PacketPtr getHeadPacket()
285 { fatal("No packets in a SpecialDataRequest"); }
286
287 /** Step on numIssuedFragments */
288 void stepToNextPacket() { }
289
290 /** Has no packets to send */
291 bool sentAllPackets() { return true; }
292
293 /** Never sends any requests */
294 bool hasPacketsInMemSystem() { return false; }
295
296 /** Keep the given packet as the response packet
297 * LSQRequest::packet */
298 void retireResponse(PacketPtr packet_) { }
299
300 public:
301 SpecialDataRequest(LSQ &port_, MinorDynInstPtr inst_) :
302 /* Say this is a load, not actually relevant */
303 LSQRequest(port_, inst_, true, NULL, 0)
304 { }
305 };
306
307 /** FailedDataRequest represents requests from instructions that
308 * failed their predicates but need to ride the requests/transfers
309 * queues to maintain trace ordering */
310 class FailedDataRequest : public SpecialDataRequest
311 {
312 public:
313 FailedDataRequest(LSQ &port_, MinorDynInstPtr inst_) :
314 SpecialDataRequest(port_, inst_)
315 { state = Failed; }
316 };
317
318 /** Request for doing barrier accounting in the store buffer. Not
319 * for use outside that unit */
320 class BarrierDataRequest : public SpecialDataRequest
321 {
322 public:
323 bool isBarrier() { return true; }
324
325 public:
326 BarrierDataRequest(LSQ &port_, MinorDynInstPtr inst_) :
327 SpecialDataRequest(port_, inst_)
328 { state = Complete; }
329 };
330
331 /** SingleDataRequest is used for requests that don't fragment */
332 class SingleDataRequest : public LSQRequest
333 {
334 protected:
335 /** TLB interace */
336 void finish(const Fault &fault_, RequestPtr request_,
337 ThreadContext *tc, BaseTLB::Mode mode);
338
339 /** Has my only packet been sent to the memory system but has not
340 * yet been responded to */
341 bool packetInFlight;
342
343 /** Has the packet been at least sent to the memory system? */
344 bool packetSent;
345
346 public:
347 /** Send single translation request */
348 void startAddrTranslation();
349
350 /** Get the head packet as counted by numIssuedFragments */
351 PacketPtr getHeadPacket() { return packet; }
352
353 /** Remember that the packet has been sent */
354 void stepToNextPacket() { packetInFlight = true; packetSent = true; }
355
356 /** Has packet been sent */
357 bool hasPacketsInMemSystem() { return packetInFlight; }
358
359 /** packetInFlight can become false again, so need to check
360 * packetSent */
361 bool sentAllPackets() { return packetSent; }
362
363 /** Keep the given packet as the response packet
364 * LSQRequest::packet */
365 void retireResponse(PacketPtr packet_);
366
367 public:
368 SingleDataRequest(LSQ &port_, MinorDynInstPtr inst_,
369 bool isLoad_, PacketDataPtr data_ = NULL, uint64_t *res_ = NULL) :
370 LSQRequest(port_, inst_, isLoad_, data_, res_),
371 packetInFlight(false),
372 packetSent(false)
373 { }
374 };
375
376 class SplitDataRequest : public LSQRequest
377 {
378 protected:
379 /** Event to step between translations */
380 class TranslationEvent : public Event
381 {
382 protected:
383 SplitDataRequest &owner;
384
385 public:
386 TranslationEvent(SplitDataRequest &owner_)
387 : owner(owner_) { }
388
389 void process()
390 { owner.sendNextFragmentToTranslation(); }
391 };
392
393 TranslationEvent translationEvent;
394 protected:
395 /** Number of fragments this request is split into */
396 unsigned int numFragments;
397
398 /** Number of fragments in the address translation mechanism */
399 unsigned int numInTranslationFragments;
400
401 /** Number of fragments that have completed address translation,
402 * (numTranslatedFragments + numInTranslationFragments) <=
403 * numFragments. When numTranslatedFramgents == numFragments,
404 * translation is complete */
405 unsigned int numTranslatedFragments;
406
407 /** Number of fragments already issued (<= numFragments) */
408 unsigned int numIssuedFragments;
409
410 /** Number of fragments retired back to this request */
411 unsigned int numRetiredFragments;
412
413 /** Fragment Requests corresponding to the address ranges of
414 * each fragment */
415 std::vector<Request *> fragmentRequests;
416
417 /** Packets matching fragmentRequests to issue fragments to memory */
418 std::vector<Packet *> fragmentPackets;
419
420 protected:
421 /** TLB response interface */
422 void finish(const Fault &fault_, RequestPtr request_,
423 ThreadContext *tc, BaseTLB::Mode mode);
424
425 public:
426 SplitDataRequest(LSQ &port_, MinorDynInstPtr inst_,
427 bool isLoad_, PacketDataPtr data_ = NULL,
428 uint64_t *res_ = NULL);
429
430 ~SplitDataRequest();
431
432 public:
433 /** Make all the Requests for this transfer's fragments so that those
434 * requests can be sent for address translation */
435 void makeFragmentRequests();
436
437 /** Make the packets to go with the requests so they can be sent to
438 * the memory system */
439 void makeFragmentPackets();
440
441 /** Start a loop of do { sendNextFragmentToTranslation ;
442 * translateTiming ; finish } while (numTranslatedFragments !=
443 * numFragments) to complete all this requests' fragments' address
444 * translations */
445 void startAddrTranslation();
446
447 /** Get the head packet as counted by numIssuedFragments */
448 PacketPtr getHeadPacket();
449
450 /** Step on numIssuedFragments */
451 void stepToNextPacket();
452
453 bool hasPacketsInMemSystem()
454 { return numIssuedFragments != numRetiredFragments; }
455
456 /** Have we stepped past the end of fragmentPackets? */
457 bool sentAllPackets() { return numIssuedFragments == numFragments; }
458
459 /** For loads, paste the response data into the main
460 * response packet */
461 void retireResponse(PacketPtr packet_);
462
463 /** Part of the address translation loop, see startAddTranslation */
464 void sendNextFragmentToTranslation();
465 };
466
467 /** Store buffer. This contains stores which have been committed
468 * but whose memory transfers have not yet been issued. Load data
469 * can be forwarded out of the store buffer */
470 class StoreBuffer : public Named
471 {
472 public:
473 /** My owner */
474 LSQ &lsq;
475
476 /** Number of slots, this is a bound on the size of slots */
477 const unsigned int numSlots;
478
479 /** Maximum number of stores that can be issued per cycle */
480 const unsigned int storeLimitPerCycle;
481
482 public:
483 /** Queue of store requests on their way to memory */
484 std::deque<LSQRequestPtr> slots;
485
486 /** Number of occupied slots which have not yet issued a
487 * memory access */
488 unsigned int numUnissuedAccesses;
489
490 public:
491 StoreBuffer(std::string name_, LSQ &lsq_,
492 unsigned int store_buffer_size,
493 unsigned int store_limit_per_cycle);
494
495 public:
496 /** Can a new request be inserted into the queue? */
497 bool canInsert() const;
498
499 /** Delete the given request and free the slot it occupied */
500 void deleteRequest(LSQRequestPtr request);
501
502 /** Insert a request at the back of the queue */
503 void insert(LSQRequestPtr request);
504
505 /** Look for a store which satisfies the given load. Returns an
506 * indication whether the forwarding request can be wholly,
507 * partly or not all all satisfied. If the request can be
508 * wholly satisfied, the store buffer slot number which can be used
509 * is returned in found_slot */
510 AddrRangeCoverage canForwardDataToLoad(LSQRequestPtr request,
511 unsigned int &found_slot);
512
513 /** Fill the given packet with appropriate date from slot
514 * slot_number */
515 void forwardStoreData(LSQRequestPtr load, unsigned int slot_number);
516
517 /** Number of stores in the store buffer which have not been
518 * completely issued to the memory system */
519 unsigned int numUnissuedStores() { return numUnissuedAccesses; }
520
521 /** Count a store being issued to memory by decrementing
522 * numUnissuedAccesses. Does not count barrier requests as they
523 * will be handles as barriers are cleared from the buffer */
524 void countIssuedStore(LSQRequestPtr request);
525
526 /** Drained if there is absolutely nothing left in the buffer */
527 bool isDrained() const { return slots.empty(); }
528
529 /** Try to issue more stores to memory */
530 void step();
531
532 /** Report queue contents for MinorTrace */
533 void minorTrace() const;
534 };
535
536 protected:
537 /** Most recent execSeqNum of a memory barrier instruction or
538 * 0 if there are no in-flight barriers. Useful as a
539 * dependency for early-issued memory operations */
540 InstSeqNum lastMemBarrier;
541
542 public:
543 /** Retry state of last issued memory transfer */
544 MemoryState state;
545
546 /** Maximum number of in-flight accesses issued to the memory system */
547 const unsigned int inMemorySystemLimit;
548
549 /** Memory system access width (and snap) in bytes */
550 const unsigned int lineWidth;
551
552 public:
553 /** The LSQ consists of three queues: requests, transfers and the
554 * store buffer storeBuffer. */
555
556 typedef Queue<LSQRequestPtr,
557 ReportTraitsPtrAdaptor<LSQRequestPtr>,
558 NoBubbleTraits<LSQRequestPtr> >
559 LSQQueue;
560
561 /** requests contains LSQRequests which have been issued to the TLB by
562 * calling ExecContext::readMem/writeMem (which in turn calls
563 * LSQ::pushRequest and LSQRequest::startAddrTranslation). Once they
564 * have a physical address, requests at the head of requests can be
565 * issued to the memory system. At this stage, it cannot be clear that
566 * memory accesses *must* happen (that there are no preceding faults or
567 * changes of flow of control) and so only cacheable reads are issued
568 * to memory.
569 * Cacheable stores are not issued at all (and just pass through
570 * 'transfers' in order) and all other transfers are stalled in requests
571 * until their corresponding instructions are at the head of the
572 * inMemInsts instruction queue and have the right streamSeqNum. */
573 LSQQueue requests;
574
575 /** Once issued to memory (or, for stores, just had their
576 * state changed to StoreToStoreBuffer) LSQRequests pass through
577 * transfers waiting for memory responses. At the head of transfers,
578 * Execute::commitInst can pick up the memory response for a request
579 * using LSQ::findResponse. Responses to be committed can then
580 * have ExecContext::completeAcc on them. Stores can then be pushed
581 * into the store buffer. All other transfers will then be complete. */
582 LSQQueue transfers;
583
584 /* The store buffer contains committed cacheable stores on
585 * their way to memory decoupled from subsequence instruction execution.
586 * Before trying to issue a cacheable read from 'requests' to memory,
587 * the store buffer is checked to see if a previous store contains the
588 * needed data (StoreBuffer::canForwardDataToLoad) which can be
589 * forwarded in lieu of a memory access. If there are outstanding
590 * stores in the transfers queue, they must be promoted to the store
591 * buffer (and so be commited) before they can be correctly checked
592 * for forwarding. */
593 StoreBuffer storeBuffer;
594
595 protected:
596 /** Count of the number of mem. accesses which have left the
597 * requests queue and are in the 'wild' in the memory system and who
598 * *must not* be interrupted as they are not normal cacheable
599 * accesses. This is a count of the number of in-flight requests
600 * with issuedToMemory set who have visited tryToSendRequest at least
601 * once */
602 unsigned int numAccessesInMemorySystem;
603
604 /** Number of requests in the DTLB in the requests queue */
605 unsigned int numAccessesInDTLB;
606
607 /** The number of stores in the transfers queue. Useful when
608 * testing if the store buffer contains all the forwardable stores */
609 unsigned int numStoresInTransfers;
610
611 /** The number of accesses which have been issued to the memory
612 * system but have not been committed/discarded *excluding*
613 * cacheable normal loads which don't need to be tracked */
614 unsigned int numAccessesIssuedToMemory;
615
616 /** The request (from either requests or the store buffer) which is
617 * currently waiting have its memory access retried */
618 LSQRequestPtr retryRequest;
619
620 /** Address Mask for a cache block (e.g. ~(cache_block_size-1)) */
621 Addr cacheBlockMask;
622
623 protected:
624 /** Try and issue a memory access for a translated request at the
625 * head of the requests queue. Also tries to move the request
626 * between queues */
627 void tryToSendToTransfers(LSQRequestPtr request);
628
629 /** Try to send (or resend) a memory request's next/only packet to
630 * the memory system. Returns true if the request was successfully
631 * sent to memory (and was also the last packet in a transfer) */
632 bool tryToSend(LSQRequestPtr request);
633
634 /** Clear a barrier (if it's the last one marked up in lastMemBarrier) */
635 void clearMemBarrier(MinorDynInstPtr inst);
636
637 /** Move a request between queues */
638 void moveFromRequestsToTransfers(LSQRequestPtr request);
639
640 /** Can a request be sent to the memory system */
641 bool canSendToMemorySystem();
642
643 public:
644 LSQ(std::string name_, std::string dcache_port_name_,
645 MinorCPU &cpu_, Execute &execute_,
646 unsigned int max_accesses_in_memory_system, unsigned int line_width,
647 unsigned int requests_queue_size, unsigned int transfers_queue_size,
648 unsigned int store_buffer_size,
649 unsigned int store_buffer_cycle_store_limit);
650
651 virtual ~LSQ();
652
653 public:
654 /** Step checks the queues to see if their are issuable transfers
655 * which were not otherwise picked up by tests at the end of other
656 * events.
657 *
658 * Steppable actions include deferred actions which couldn't be
659 * cascaded on the end of a memory response/TLB response event
660 * because of resource congestion. */
661 void step();
662
663 /** Is their space in the request queue to be able to push a request by
664 * issuing an isMemRef instruction */
665 bool canRequest() { return requests.unreservedRemainingSpace() != 0; }
666
667 /** Returns a response if it's at the head of the transfers queue and
668 * it's either complete or can be sent on to the store buffer. After
669 * calling, the request still remains on the transfer queue until
670 * popResponse is called */
671 LSQRequestPtr findResponse(MinorDynInstPtr inst);
672
673 /** Sanity check and pop the head response */
674 void popResponse(LSQRequestPtr response);
675
676 /** Must check this before trying to insert into the store buffer */
677 bool canPushIntoStoreBuffer() const { return storeBuffer.canInsert(); }
678
679 /** A store has been committed, please move it to the store buffer */
680 void sendStoreToStoreBuffer(LSQRequestPtr request);
681
682 /** Are there any accesses other than normal cached loads in the
683 * memory system or having received responses which need to be
684 * handled for their instruction's to be completed */
685 bool accessesInFlight() const
686 { return numAccessesIssuedToMemory != 0; }
687
688 /** A memory barrier instruction has been issued, remember its
689 * execSeqNum that we can avoid issuing memory ops until it is
690 * committed */
691 void issuedMemBarrierInst(MinorDynInstPtr inst);
692
693 /** Get the execSeqNum of the last issued memory barrier */
694 InstSeqNum getLastMemBarrier() const { return lastMemBarrier; }
695
696 /** Is there nothing left in the LSQ */
697 bool isDrained();
698
699 /** May need to be ticked next cycle as one of the queues contains
700 * an actionable transfers or address translation */
701 bool needsToTick();
702
703 /** Complete a barrier instruction. Where committed, makes a
704 * BarrierDataRequest and pushed it into the store buffer */
705 void completeMemBarrierInst(MinorDynInstPtr inst,
706 bool committed);
707
708 /** Single interface for readMem/writeMem to issue requests into
709 * the LSQ */
710 void pushRequest(MinorDynInstPtr inst, bool isLoad, uint8_t *data,
711 unsigned int size, Addr addr, unsigned int flags, uint64_t *res);
712
713 /** Push a predicate failed-representing request into the queues just
714 * to maintain commit order */
715 void pushFailedRequest(MinorDynInstPtr inst);
716
717 /** Memory interface */
718 bool recvTimingResp(PacketPtr pkt);
719 void recvReqRetry();
720 void recvTimingSnoopReq(PacketPtr pkt);
721
722 /** Return the raw-bindable port */
723 MinorCPU::MinorCPUPort &getDcachePort() { return dcachePort; }
724
725 void minorTrace() const;
726};
727
728/** Make a suitable packet for the given request. If the request is a store,
729 * data will be the payload data. If sender_state is NULL, it won't be
730 * pushed into the packet as senderState */
731PacketPtr makePacketForRequest(Request &request, bool isLoad,
732 Packet::SenderState *sender_state = NULL, PacketDataPtr data = NULL);
733}
734
735#endif /* __CPU_MINOR_NEW_LSQ_HH__ */