lsq.hh (13560:f8732494c155) lsq.hh (13590:d7e018859709)
1/*
1/*
2 * Copyright (c) 2011-2012, 2014 ARM Limited
2 * Copyright (c) 2011-2012, 2014, 2018 ARM Limited
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
4 * All rights reserved
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder. You may use the software subject to the license

--- 31 unchanged lines hidden (view full) ---

42 */
43
44#ifndef __CPU_O3_LSQ_HH__
45#define __CPU_O3_LSQ_HH__
46
47#include <map>
48#include <queue>
49
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
4 * All rights reserved
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder. You may use the software subject to the license

--- 31 unchanged lines hidden (view full) ---

42 */
43
44#ifndef __CPU_O3_LSQ_HH__
45#define __CPU_O3_LSQ_HH__
46
47#include <map>
48#include <queue>
49
50#include "cpu/o3/lsq_unit.hh"
50#include "arch/generic/tlb.hh"
51#include "cpu/inst_seq.hh"
51#include "cpu/inst_seq.hh"
52#include "cpu/o3/lsq_unit.hh"
52#include "enums/SMTQueuePolicy.hh"
53#include "mem/port.hh"
54#include "sim/sim_object.hh"
55
56struct DerivO3CPUParams;
57
58template <class Impl>
53#include "enums/SMTQueuePolicy.hh"
54#include "mem/port.hh"
55#include "sim/sim_object.hh"
56
57struct DerivO3CPUParams;
58
59template <class Impl>
59class LSQ {
60class LSQ
61
62{
60 public:
61 typedef typename Impl::O3CPU O3CPU;
62 typedef typename Impl::DynInstPtr DynInstPtr;
63 typedef typename Impl::CPUPol::IEW IEW;
64 typedef typename Impl::CPUPol::LSQUnit LSQUnit;
65
63 public:
64 typedef typename Impl::O3CPU O3CPU;
65 typedef typename Impl::DynInstPtr DynInstPtr;
66 typedef typename Impl::CPUPol::IEW IEW;
67 typedef typename Impl::CPUPol::LSQUnit LSQUnit;
68
69 class LSQRequest;
70 /** Derived class to hold any sender state the LSQ needs. */
71 class LSQSenderState : public Packet::SenderState
72 {
73 protected:
74 /** The senderState needs to know the LSQRequest who owns it. */
75 LSQRequest* _request;
76
77 /** Default constructor. */
78 LSQSenderState(LSQRequest* request, bool isLoad_)
79 : _request(request), mainPkt(nullptr), pendingPacket(nullptr),
80 outstanding(0), isLoad(isLoad_), needWB(isLoad_), isSplit(false),
81 pktToSend(false), deleted(false)
82 { }
83 public:
84
85 /** Instruction which initiated the access to memory. */
86 DynInstPtr inst;
87 /** The main packet from a split load, used during writeback. */
88 PacketPtr mainPkt;
89 /** A second packet from a split store that needs sending. */
90 PacketPtr pendingPacket;
91 /** Number of outstanding packets to complete. */
92 uint8_t outstanding;
93 /** Whether or not it is a load. */
94 bool isLoad;
95 /** Whether or not the instruction will need to writeback. */
96 bool needWB;
97 /** Whether or not this access is split in two. */
98 bool isSplit;
99 /** Whether or not there is a packet that needs sending. */
100 bool pktToSend;
101 /** Has the request been deleted?
102 * LSQ entries can be squashed before the response comes back. in that
103 * case the SenderState knows.
104 */
105 bool deleted;
106 ContextID contextId() { return inst->contextId(); }
107
108 /** Completes a packet and returns whether the access is finished. */
109 inline bool isComplete() { return outstanding == 0; }
110 inline void deleteRequest() { deleted = true; }
111 inline bool alive() { return !deleted; }
112 LSQRequest* request() { return _request; }
113 virtual void complete() = 0;
114 void writebackDone() { _request->writebackDone(); }
115 };
116
117 /** Memory operation metadata.
118 * This class holds the information about a memory operation. It lives
119 * from initiateAcc to resource deallocation at commit or squash.
120 * LSQRequest objects are owned by the LQ/SQ Entry in the LSQUnit that
121 * holds the operation. It is also used by the LSQSenderState. In addition,
122 * the LSQRequest is a TranslationState, therefore, upon squash, there must
123 * be a defined ownership transferal in case the LSQ resources are
124 * deallocated before the TLB is done using the TranslationState. If that
125 * happens, the LSQRequest will be self-owned, and responsible to detect
126 * that its services are no longer required and self-destruct.
127 *
128 * Lifetime of a LSQRequest:
129 * +--------------------+
130 * |LSQ creates and owns|
131 * +--------------------+
132 * |
133 * +--------------------+
134 * | Initate translation|
135 * +--------------------+
136 * |
137 * ___^___
138 * ___/ \___
139 * ______/ Squashed? \
140 * | \___ ___/
141 * | \___ ___/
142 * | v
143 * | |
144 * | +--------------------+
145 * | | Translation done |
146 * | +--------------------+
147 * | |
148 * | +--------------------+
149 * | | Send packet |<------+
150 * | +--------------------+ |
151 * | | |
152 * | ___^___ |
153 * | ___/ \___ |
154 * | ____/ Squashed? \ |
155 * | | \___ ___/ |
156 * | | \___ ___/ |
157 * | | v |
158 * | | | |
159 * | | ___^___ |
160 * | | ___/ \___ |
161 * | | / Done? \__________|
162 * | | \___ ___/
163 * | | \___ ___/
164 * | | v
165 * | | |
166 * | | +--------------------+
167 * | | | Manage stuff |
168 * | | | Free resources |
169 * | | +--------------------+
170 * | |
171 * | | +--------------------+
172 * | | | senderState owns |
173 * | +->| onRecvTimingResp |
174 * | | free resources |
175 * | +--------------------+
176 * |
177 * | +----------------------+
178 * | | self owned (Trans) |
179 * +-->| on TranslationFinish |
180 * | free resources |
181 * +----------------------+
182 *
183 *
184 */
185 class LSQRequest : public BaseTLB::Translation
186 {
187 protected:
188 typedef uint32_t FlagsStorage;
189 typedef ::Flags<FlagsStorage> FlagsType;
190
191 enum Flag : FlagsStorage
192 {
193 IsLoad = 0x00000001,
194 /** True if this is a store that writes registers (SC). */
195 WbStore = 0x00000002,
196 Delayed = 0x00000004,
197 IsSplit = 0x00000008,
198 /** True if any translation has been sent to TLB. */
199 TranslationStarted = 0x00000010,
200 /** True if there are un-replied outbound translations.. */
201 TranslationFinished = 0x00000020,
202 Sent = 0x00000040,
203 Retry = 0x00000080,
204 Complete = 0x00000100,
205 /** Ownership tracking flags. */
206 /** Translation squashed. */
207 TranslationSquashed = 0x00000200,
208 /** Request discarded */
209 Discarded = 0x00000400,
210 /** LSQ resources freed. */
211 LSQEntryFreed = 0x00000800,
212 /** Store written back. */
213 WritebackScheduled = 0x00001000,
214 WritebackDone = 0x00002000
215 };
216 FlagsType flags;
217
218 enum class State
219 {
220 NotIssued,
221 Translation,
222 Request,
223 Complete,
224 Squashed,
225 Fault,
226 };
227 State _state;
228 LSQSenderState* _senderState;
229 void setState(const State& newState) { _state = newState; }
230
231 uint32_t numTranslatedFragments;
232 uint32_t numInTranslationFragments;
233
234 /** LQ/SQ entry idx. */
235 uint32_t _entryIdx;
236
237 void markDelayed() { flags.set(Flag::Delayed); }
238 bool isDelayed() { return flags.isSet(Flag::Delayed); }
239
240 public:
241 LSQUnit& _port;
242 const DynInstPtr _inst;
243 uint32_t _taskId;
244 PacketDataPtr _data;
245 std::vector<PacketPtr> _packets;
246 std::vector<RequestPtr> _requests;
247 std::vector<Fault> _fault;
248 uint64_t* _res;
249 const Addr _addr;
250 const uint32_t _size;
251 const Request::Flags _flags;
252 uint32_t _numOutstandingPackets;
253 protected:
254 LSQUnit* lsqUnit() { return &_port; }
255 LSQRequest(LSQUnit* port, const DynInstPtr& inst, bool isLoad) :
256 _state(State::NotIssued), _senderState(nullptr),
257 _port(*port), _inst(inst), _data(nullptr),
258 _res(nullptr), _addr(0), _size(0), _flags(0),
259 _numOutstandingPackets(0)
260 {
261 flags.set(Flag::IsLoad, isLoad);
262 flags.set(Flag::WbStore, _inst->isStoreConditional());
263 install();
264 }
265 LSQRequest(LSQUnit* port, const DynInstPtr& inst, bool isLoad,
266 const Addr& addr, const uint32_t& size,
267 const Request::Flags& flags_,
268 PacketDataPtr data = nullptr, uint64_t* res = nullptr)
269 : _state(State::NotIssued), _senderState(nullptr),
270 numTranslatedFragments(0),
271 numInTranslationFragments(0),
272 _port(*port), _inst(inst), _data(data),
273 _res(res), _addr(addr), _size(size),
274 _flags(flags_),
275 _numOutstandingPackets(0)
276 {
277 flags.set(Flag::IsLoad, isLoad);
278 flags.set(Flag::WbStore, _inst->isStoreConditional());
279 install();
280 }
281
282 bool
283 isLoad() const
284 {
285 return flags.isSet(Flag::IsLoad);
286 }
287
288 /** Install the request in the LQ/SQ. */
289 void install()
290 {
291 if (isLoad()) {
292 _port.loadQueue[_inst->lqIdx].setRequest(this);
293 } else {
294 _port.storeQueue[_inst->sqIdx].setRequest(this);
295 }
296 }
297 virtual bool
298 squashed() const override
299 {
300 return _inst->isSquashed();
301 }
302
303 /**
304 * Test if the LSQRequest has been released, i.e. self-owned.
305 * An LSQRequest manages itself when the resources on the LSQ are freed
306 * but the translation is still going on and the LSQEntry was freed.
307 */
308 bool
309 isReleased()
310 {
311 return flags.isSet(Flag::LSQEntryFreed) ||
312 flags.isSet(Flag::Discarded);
313 }
314
315 /** Release the LSQRequest.
316 * Notify the sender state that the request it points to is not valid
317 * anymore. Understand if the request is orphan (self-managed) and if
318 * so, mark it as freed, else destroy it, as this means
319 * the end of its life cycle.
320 * An LSQRequest is orphan when its resources are released
321 * but there is any in-flight translation request to the TLB or access
322 * request to the memory.
323 */
324 void release(Flag reason)
325 {
326 assert(reason == Flag::LSQEntryFreed || reason == Flag::Discarded);
327 if (!isAnyOutstandingRequest()) {
328 delete this;
329 } else {
330 if (_senderState) {
331 _senderState->deleteRequest();
332 }
333 flags.set(reason);
334 }
335 }
336
337 /** Destructor.
338 * The LSQRequest owns the request. If the packet has already been
339 * sent, the sender state will be deleted upon receiving the reply.
340 */
341 virtual ~LSQRequest()
342 {
343 assert(!isAnyOutstandingRequest());
344 _inst->savedReq = nullptr;
345 if (_senderState)
346 delete _senderState;
347
348 for (auto r: _packets)
349 delete r;
350 };
351
352
353 public:
354 /** Convenience getters/setters. */
355 /** @{ */
356 /** Set up Context numbers. */
357 void
358 setContext(const ContextID& context_id)
359 {
360 request()->setContext(context_id);
361 }
362
363 const DynInstPtr&
364 instruction()
365 {
366 return _inst;
367 }
368
369 /** Set up virtual request.
370 * For a previously allocated Request objects.
371 */
372 void
373 setVirt(int asid, Addr vaddr, unsigned size, Request::Flags flags_,
374 MasterID mid, Addr pc)
375 {
376 request()->setVirt(asid, vaddr, size, flags_, mid, pc);
377 }
378
379 void
380 taskId(const uint32_t& v)
381 {
382 _taskId = v;
383 for (auto& r: _requests)
384 r->taskId(v);
385 }
386
387 uint32_t taskId() const { return _taskId; }
388 RequestPtr request(int idx = 0) { return _requests.at(idx); }
389
390 const RequestPtr
391 request(int idx = 0) const
392 {
393 return _requests.at(idx);
394 }
395
396 Addr getVaddr(int idx = 0) const { return request(idx)->getVaddr(); }
397 virtual void initiateTranslation() = 0;
398
399 PacketPtr packet(int idx = 0) { return _packets.at(idx); }
400
401 virtual PacketPtr
402 mainPacket()
403 {
404 assert (_packets.size() == 1);
405 return packet();
406 }
407
408 virtual RequestPtr
409 mainRequest()
410 {
411 assert (_requests.size() == 1);
412 return request();
413 }
414
415 void
416 senderState(LSQSenderState* st)
417 {
418 _senderState = st;
419 for (auto& pkt: _packets) {
420 if (pkt)
421 pkt->senderState = st;
422 }
423 }
424
425 const LSQSenderState*
426 senderState() const
427 {
428 return _senderState;
429 }
430
431 /**
432 * Mark senderState as discarded. This will cause to discard response
433 * packets from the cache.
434 */
435 void
436 discardSenderState()
437 {
438 assert(_senderState);
439 _senderState->deleteRequest();
440 }
441
442 /**
443 * Test if there is any in-flight translation or mem access request
444 */
445 bool
446 isAnyOutstandingRequest()
447 {
448 return numInTranslationFragments > 0 ||
449 _numOutstandingPackets > 0 ||
450 (flags.isSet(Flag::WritebackScheduled) &&
451 !flags.isSet(Flag::WritebackDone));
452 }
453
454 bool
455 isSplit() const
456 {
457 return flags.isSet(Flag::IsSplit);
458 }
459 /** @} */
460 virtual bool recvTimingResp(PacketPtr pkt) = 0;
461 virtual void sendPacketToCache() = 0;
462 virtual void buildPackets() = 0;
463
464 /**
465 * Memory mapped IPR accesses
466 */
467 virtual void handleIprWrite(ThreadContext *thread, PacketPtr pkt) = 0;
468 virtual Cycles handleIprRead(ThreadContext *thread, PacketPtr pkt) = 0;
469
470 /**
471 * Test if the request accesses a particular cache line.
472 */
473 virtual bool isCacheBlockHit(Addr blockAddr, Addr cacheBlockMask) = 0;
474
475 /** Update the status to reflect that a packet was sent. */
476 void
477 packetSent()
478 {
479 flags.set(Flag::Sent);
480 }
481 /** Update the status to reflect that a packet was not sent.
482 * When a packet fails to be sent, we mark the request as needing a
483 * retry. Note that Retry flag is sticky.
484 */
485 void
486 packetNotSent()
487 {
488 flags.set(Flag::Retry);
489 flags.clear(Flag::Sent);
490 }
491
492 void sendFragmentToTranslation(int i);
493 bool
494 isComplete()
495 {
496 return flags.isSet(Flag::Complete);
497 }
498
499 bool
500 isInTranslation()
501 {
502 return _state == State::Translation;
503 }
504
505 bool
506 isTranslationComplete()
507 {
508 return flags.isSet(Flag::TranslationStarted) &&
509 !isInTranslation();
510 }
511
512 bool
513 isTranslationBlocked()
514 {
515 return _state == State::Translation &&
516 flags.isSet(Flag::TranslationStarted) &&
517 !flags.isSet(Flag::TranslationFinished);
518 }
519
520 bool
521 isSent()
522 {
523 return flags.isSet(Flag::Sent);
524 }
525
526 /**
527 * The LSQ entry is cleared
528 */
529 void
530 freeLSQEntry()
531 {
532 release(Flag::LSQEntryFreed);
533 }
534
535 /**
536 * The request is discarded (e.g. partial store-load forwarding)
537 */
538 void
539 discard()
540 {
541 release(Flag::Discarded);
542 }
543
544 void
545 packetReplied()
546 {
547 assert(_numOutstandingPackets > 0);
548 _numOutstandingPackets--;
549 if (_numOutstandingPackets == 0 && isReleased())
550 delete this;
551 }
552
553 void
554 writebackScheduled()
555 {
556 assert(!flags.isSet(Flag::WritebackScheduled));
557 flags.set(Flag::WritebackScheduled);
558 }
559
560 void
561 writebackDone()
562 {
563 flags.set(Flag::WritebackDone);
564 /* If the lsq resources are already free */
565 if (isReleased()) {
566 delete this;
567 }
568 }
569
570 void
571 squashTranslation()
572 {
573 assert(numInTranslationFragments == 0);
574 flags.set(Flag::TranslationSquashed);
575 /* If we are on our own, self-destruct. */
576 if (isReleased()) {
577 delete this;
578 }
579 }
580
581 void
582 complete()
583 {
584 flags.set(Flag::Complete);
585 }
586 };
587
588 class SingleDataRequest : public LSQRequest
589 {
590 protected:
591 /* Given that we are inside templates, children need explicit
592 * declaration of the names in the parent class. */
593 using Flag = typename LSQRequest::Flag;
594 using State = typename LSQRequest::State;
595 using LSQRequest::_fault;
596 using LSQRequest::_inst;
597 using LSQRequest::_packets;
598 using LSQRequest::_port;
599 using LSQRequest::_res;
600 using LSQRequest::_senderState;
601 using LSQRequest::_state;
602 using LSQRequest::flags;
603 using LSQRequest::isLoad;
604 using LSQRequest::isTranslationComplete;
605 using LSQRequest::lsqUnit;
606 using LSQRequest::request;
607 using LSQRequest::sendFragmentToTranslation;
608 using LSQRequest::setState;
609 using LSQRequest::numInTranslationFragments;
610 using LSQRequest::numTranslatedFragments;
611 using LSQRequest::_numOutstandingPackets;
612 public:
613 SingleDataRequest(LSQUnit* port, const DynInstPtr& inst, bool isLoad,
614 const Addr& addr, const uint32_t& size,
615 const Request::Flags& flags_,
616 PacketDataPtr data = nullptr,
617 uint64_t* res = nullptr) :
618 LSQRequest(port, inst, isLoad, addr, size, flags_, data, res)
619 {
620 LSQRequest::_requests.push_back(
621 std::make_shared<Request>(inst->getASID(), addr, size, flags_,
622 inst->masterId(), inst->instAddr(), inst->contextId()));
623 LSQRequest::_requests.back()->setReqInstSeqNum(inst->seqNum);
624 }
625 inline virtual ~SingleDataRequest() {}
626 virtual void initiateTranslation();
627 virtual void finish(const Fault &fault, const RequestPtr &req,
628 ThreadContext* tc, BaseTLB::Mode mode);
629 virtual bool recvTimingResp(PacketPtr pkt);
630 virtual void sendPacketToCache();
631 virtual void buildPackets();
632 virtual void handleIprWrite(ThreadContext *thread, PacketPtr pkt);
633 virtual Cycles handleIprRead(ThreadContext *thread, PacketPtr pkt);
634 virtual bool isCacheBlockHit(Addr blockAddr, Addr cacheBlockMask);
635 };
636
637 class SplitDataRequest : public LSQRequest
638 {
639 protected:
640 /* Given that we are inside templates, children need explicit
641 * declaration of the names in the parent class. */
642 using Flag = typename LSQRequest::Flag;
643 using State = typename LSQRequest::State;
644 using LSQRequest::_addr;
645 using LSQRequest::_data;
646 using LSQRequest::_fault;
647 using LSQRequest::_flags;
648 using LSQRequest::_inst;
649 using LSQRequest::_packets;
650 using LSQRequest::_port;
651 using LSQRequest::_requests;
652 using LSQRequest::_res;
653 using LSQRequest::_senderState;
654 using LSQRequest::_size;
655 using LSQRequest::_state;
656 using LSQRequest::_taskId;
657 using LSQRequest::flags;
658 using LSQRequest::isLoad;
659 using LSQRequest::isTranslationComplete;
660 using LSQRequest::lsqUnit;
661 using LSQRequest::numInTranslationFragments;
662 using LSQRequest::numTranslatedFragments;
663 using LSQRequest::request;
664 using LSQRequest::sendFragmentToTranslation;
665 using LSQRequest::setState;
666 using LSQRequest::_numOutstandingPackets;
667
668 uint32_t numFragments;
669 uint32_t numReceivedPackets;
670 RequestPtr mainReq;
671 PacketPtr _mainPacket;
672
673
674 public:
675 SplitDataRequest(LSQUnit* port, const DynInstPtr& inst, bool isLoad,
676 const Addr& addr, const uint32_t& size,
677 const Request::Flags & flags_,
678 PacketDataPtr data = nullptr,
679 uint64_t* res = nullptr) :
680 LSQRequest(port, inst, isLoad, addr, size, flags_, data, res),
681 numFragments(0),
682 numReceivedPackets(0),
683 mainReq(nullptr),
684 _mainPacket(nullptr)
685 {
686 flags.set(Flag::IsSplit);
687 }
688 virtual ~SplitDataRequest()
689 {
690 if (mainReq) {
691 mainReq = nullptr;
692 }
693 if (_mainPacket) {
694 delete _mainPacket;
695 _mainPacket = nullptr;
696 }
697 }
698 virtual void finish(const Fault &fault, const RequestPtr &req,
699 ThreadContext* tc, BaseTLB::Mode mode);
700 virtual bool recvTimingResp(PacketPtr pkt);
701 virtual void initiateTranslation();
702 virtual void sendPacketToCache();
703 virtual void buildPackets();
704
705 virtual void handleIprWrite(ThreadContext *thread, PacketPtr pkt);
706 virtual Cycles handleIprRead(ThreadContext *thread, PacketPtr pkt);
707 virtual bool isCacheBlockHit(Addr blockAddr, Addr cacheBlockMask);
708
709 virtual RequestPtr mainRequest();
710 virtual PacketPtr mainPacket();
711 };
712
66 /** Constructs an LSQ with the given parameters. */
67 LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params);
68 ~LSQ() { }
69
70 /** Returns the name of the LSQ. */
71 std::string name() const;
72
73 /** Registers statistics of each LSQ unit. */

--- 6 unchanged lines hidden (view full) ---

80 void drainSanityCheck() const;
81 /** Has the LSQ drained? */
82 bool isDrained() const;
83 /** Takes over execution from another CPU's thread. */
84 void takeOverFrom();
85
86 /** Number of entries needed for the given amount of threads.*/
87 int entryAmount(ThreadID num_threads);
713 /** Constructs an LSQ with the given parameters. */
714 LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params);
715 ~LSQ() { }
716
717 /** Returns the name of the LSQ. */
718 std::string name() const;
719
720 /** Registers statistics of each LSQ unit. */

--- 6 unchanged lines hidden (view full) ---

727 void drainSanityCheck() const;
728 /** Has the LSQ drained? */
729 bool isDrained() const;
730 /** Takes over execution from another CPU's thread. */
731 void takeOverFrom();
732
733 /** Number of entries needed for the given amount of threads.*/
734 int entryAmount(ThreadID num_threads);
88 void removeEntries(ThreadID tid);
89 /** Reset the max entries for each thread. */
90 void resetEntries();
91 /** Resize the max entries for a thread. */
92 void resizeEntries(unsigned size, ThreadID tid);
93
94 /** Ticks the LSQ. */
735
736 /** Ticks the LSQ. */
95 void tick();
96 /** Ticks a specific LSQ Unit. */
97 void tick(ThreadID tid)
98 { thread[tid].tick(); }
737 void tick() { usedStorePorts = 0; }
99
100 /** Inserts a load into the LSQ. */
101 void insertLoad(const DynInstPtr &load_inst);
102 /** Inserts a store into the LSQ. */
103 void insertStore(const DynInstPtr &store_inst);
104
105 /** Executes a load. */
106 Fault executeLoad(const DynInstPtr &inst);
107
108 /** Executes a store. */
109 Fault executeStore(const DynInstPtr &inst);
110
111 /**
112 * Commits loads up until the given sequence number for a specific thread.
113 */
114 void commitLoads(InstSeqNum &youngest_inst, ThreadID tid)
738
739 /** Inserts a load into the LSQ. */
740 void insertLoad(const DynInstPtr &load_inst);
741 /** Inserts a store into the LSQ. */
742 void insertStore(const DynInstPtr &store_inst);
743
744 /** Executes a load. */
745 Fault executeLoad(const DynInstPtr &inst);
746
747 /** Executes a store. */
748 Fault executeStore(const DynInstPtr &inst);
749
750 /**
751 * Commits loads up until the given sequence number for a specific thread.
752 */
753 void commitLoads(InstSeqNum &youngest_inst, ThreadID tid)
115 { thread[tid].commitLoads(youngest_inst); }
754 { thread.at(tid).commitLoads(youngest_inst); }
116
117 /**
118 * Commits stores up until the given sequence number for a specific thread.
119 */
120 void commitStores(InstSeqNum &youngest_inst, ThreadID tid)
755
756 /**
757 * Commits stores up until the given sequence number for a specific thread.
758 */
759 void commitStores(InstSeqNum &youngest_inst, ThreadID tid)
121 { thread[tid].commitStores(youngest_inst); }
760 { thread.at(tid).commitStores(youngest_inst); }
122
123 /**
124 * Attempts to write back stores until all cache ports are used or the
125 * interface becomes blocked.
126 */
127 void writebackStores();
128 /** Same as above, but only for one thread. */
129 void writebackStores(ThreadID tid);
130
131 /**
132 * Squash instructions from a thread until the specified sequence number.
133 */
761
762 /**
763 * Attempts to write back stores until all cache ports are used or the
764 * interface becomes blocked.
765 */
766 void writebackStores();
767 /** Same as above, but only for one thread. */
768 void writebackStores(ThreadID tid);
769
770 /**
771 * Squash instructions from a thread until the specified sequence number.
772 */
134 void squash(const InstSeqNum &squashed_num, ThreadID tid)
135 { thread[tid].squash(squashed_num); }
773 void
774 squash(const InstSeqNum &squashed_num, ThreadID tid)
775 {
776 thread.at(tid).squash(squashed_num);
777 }
136
137 /** Returns whether or not there was a memory ordering violation. */
138 bool violation();
139 /**
140 * Returns whether or not there was a memory ordering violation for a
141 * specific thread.
142 */
778
779 /** Returns whether or not there was a memory ordering violation. */
780 bool violation();
781 /**
782 * Returns whether or not there was a memory ordering violation for a
783 * specific thread.
784 */
143 bool violation(ThreadID tid)
144 { return thread[tid].violation(); }
785 bool violation(ThreadID tid) { return thread.at(tid).violation(); }
145
146 /** Gets the instruction that caused the memory ordering violation. */
786
787 /** Gets the instruction that caused the memory ordering violation. */
147 DynInstPtr getMemDepViolator(ThreadID tid)
148 { return thread[tid].getMemDepViolator(); }
788 DynInstPtr
789 getMemDepViolator(ThreadID tid)
790 {
791 return thread.at(tid).getMemDepViolator();
792 }
149
150 /** Returns the head index of the load queue for a specific thread. */
793
794 /** Returns the head index of the load queue for a specific thread. */
151 int getLoadHead(ThreadID tid)
152 { return thread[tid].getLoadHead(); }
795 int getLoadHead(ThreadID tid) { return thread.at(tid).getLoadHead(); }
153
154 /** Returns the sequence number of the head of the load queue. */
796
797 /** Returns the sequence number of the head of the load queue. */
155 InstSeqNum getLoadHeadSeqNum(ThreadID tid)
798 InstSeqNum
799 getLoadHeadSeqNum(ThreadID tid)
156 {
800 {
157 return thread[tid].getLoadHeadSeqNum();
801 return thread.at(tid).getLoadHeadSeqNum();
158 }
159
160 /** Returns the head index of the store queue. */
802 }
803
804 /** Returns the head index of the store queue. */
161 int getStoreHead(ThreadID tid)
162 { return thread[tid].getStoreHead(); }
805 int getStoreHead(ThreadID tid) { return thread.at(tid).getStoreHead(); }
163
164 /** Returns the sequence number of the head of the store queue. */
806
807 /** Returns the sequence number of the head of the store queue. */
165 InstSeqNum getStoreHeadSeqNum(ThreadID tid)
808 InstSeqNum
809 getStoreHeadSeqNum(ThreadID tid)
166 {
810 {
167 return thread[tid].getStoreHeadSeqNum();
811 return thread.at(tid).getStoreHeadSeqNum();
168 }
169
170 /** Returns the number of instructions in all of the queues. */
171 int getCount();
172 /** Returns the number of instructions in the queues of one thread. */
812 }
813
814 /** Returns the number of instructions in all of the queues. */
815 int getCount();
816 /** Returns the number of instructions in the queues of one thread. */
173 int getCount(ThreadID tid)
174 { return thread[tid].getCount(); }
817 int getCount(ThreadID tid) { return thread.at(tid).getCount(); }
175
176 /** Returns the total number of loads in the load queue. */
177 int numLoads();
178 /** Returns the total number of loads for a single thread. */
818
819 /** Returns the total number of loads in the load queue. */
820 int numLoads();
821 /** Returns the total number of loads for a single thread. */
179 int numLoads(ThreadID tid)
180 { return thread[tid].numLoads(); }
822 int numLoads(ThreadID tid) { return thread.at(tid).numLoads(); }
181
182 /** Returns the total number of stores in the store queue. */
183 int numStores();
184 /** Returns the total number of stores for a single thread. */
823
824 /** Returns the total number of stores in the store queue. */
825 int numStores();
826 /** Returns the total number of stores for a single thread. */
185 int numStores(ThreadID tid)
186 { return thread[tid].numStores(); }
827 int numStores(ThreadID tid) { return thread.at(tid).numStores(); }
187
188 /** Returns the number of free load entries. */
189 unsigned numFreeLoadEntries();
190
191 /** Returns the number of free store entries. */
192 unsigned numFreeStoreEntries();
193
194 /** Returns the number of free entries for a specific thread. */

--- 42 unchanged lines hidden (view full) ---

237 bool isStalled(ThreadID tid);
238
239 /** Returns whether or not there are any stores to write back to memory. */
240 bool hasStoresToWB();
241
242 /** Returns whether or not a specific thread has any stores to write back
243 * to memory.
244 */
828
829 /** Returns the number of free load entries. */
830 unsigned numFreeLoadEntries();
831
832 /** Returns the number of free store entries. */
833 unsigned numFreeStoreEntries();
834
835 /** Returns the number of free entries for a specific thread. */

--- 42 unchanged lines hidden (view full) ---

878 bool isStalled(ThreadID tid);
879
880 /** Returns whether or not there are any stores to write back to memory. */
881 bool hasStoresToWB();
882
883 /** Returns whether or not a specific thread has any stores to write back
884 * to memory.
885 */
245 bool hasStoresToWB(ThreadID tid)
246 { return thread[tid].hasStoresToWB(); }
886 bool hasStoresToWB(ThreadID tid) { return thread.at(tid).hasStoresToWB(); }
247
248 /** Returns the number of stores a specific thread has to write back. */
887
888 /** Returns the number of stores a specific thread has to write back. */
249 int numStoresToWB(ThreadID tid)
250 { return thread[tid].numStoresToWB(); }
889 int numStoresToWB(ThreadID tid) { return thread.at(tid).numStoresToWB(); }
251
252 /** Returns if the LSQ will write back to memory this cycle. */
253 bool willWB();
254 /** Returns if the LSQ of a specific thread will write back to memory this
255 * cycle.
256 */
890
891 /** Returns if the LSQ will write back to memory this cycle. */
892 bool willWB();
893 /** Returns if the LSQ of a specific thread will write back to memory this
894 * cycle.
895 */
257 bool willWB(ThreadID tid)
258 { return thread[tid].willWB(); }
896 bool willWB(ThreadID tid) { return thread.at(tid).willWB(); }
259
260 /** Debugging function to print out all instructions. */
261 void dumpInsts() const;
262 /** Debugging function to print out instructions from a specific thread. */
897
898 /** Debugging function to print out all instructions. */
899 void dumpInsts() const;
900 /** Debugging function to print out instructions from a specific thread. */
263 void dumpInsts(ThreadID tid) const
264 { thread[tid].dumpInsts(); }
901 void dumpInsts(ThreadID tid) const { thread.at(tid).dumpInsts(); }
265
266 /** Executes a read operation, using the load specified at the load
267 * index.
268 */
902
903 /** Executes a read operation, using the load specified at the load
904 * index.
905 */
269 Fault read(const RequestPtr &req,
270 RequestPtr &sreqLow, RequestPtr &sreqHigh,
271 int load_idx);
906 Fault read(LSQRequest* req, int load_idx);
272
273 /** Executes a store operation, using the store specified at the store
274 * index.
275 */
907
908 /** Executes a store operation, using the store specified at the store
909 * index.
910 */
276 Fault write(const RequestPtr &req,
277 const RequestPtr &sreqLow, const RequestPtr &sreqHigh,
278 uint8_t *data, int store_idx);
911 Fault write(LSQRequest* req, uint8_t *data, int store_idx);
279
280 /**
281 * Retry the previous send that failed.
282 */
283 void recvReqRetry();
284
912
913 /**
914 * Retry the previous send that failed.
915 */
916 void recvReqRetry();
917
918 void completeDataAccess(PacketPtr pkt);
285 /**
286 * Handles writing back and completing the load or store that has
287 * returned from memory.
288 *
289 * @param pkt Response packet from the memory sub-system
290 */
291 bool recvTimingResp(PacketPtr pkt);
292
293 void recvTimingSnoopReq(PacketPtr pkt);
294
919 /**
920 * Handles writing back and completing the load or store that has
921 * returned from memory.
922 *
923 * @param pkt Response packet from the memory sub-system
924 */
925 bool recvTimingResp(PacketPtr pkt);
926
927 void recvTimingSnoopReq(PacketPtr pkt);
928
929 Fault pushRequest(const DynInstPtr& inst, bool isLoad, uint8_t *data,
930 unsigned int size, Addr addr, Request::Flags flags,
931 uint64_t *res);
932
295 /** The CPU pointer. */
296 O3CPU *cpu;
297
298 /** The IEW stage pointer. */
299 IEW *iewStage;
300
933 /** The CPU pointer. */
934 O3CPU *cpu;
935
936 /** The IEW stage pointer. */
937 IEW *iewStage;
938
939 /** Is D-cache blocked? */
940 bool cacheBlocked() const;
941 /** Set D-cache blocked status */
942 void cacheBlocked(bool v);
943 /** Is any store port available to use? */
944 bool storePortAvailable() const;
945 /** Another store port is in use */
946 void storePortBusy();
947
301 protected:
948 protected:
949 /** D-cache is blocked */
950 bool _cacheBlocked;
951 /** The number of cache ports available each cycle (stores only). */
952 int cacheStorePorts;
953 /** The number of used cache ports in this cycle by stores. */
954 int usedStorePorts;
955
956
302 /** The LSQ policy for SMT mode. */
303 SMTQueuePolicy lsqPolicy;
304
305 /** Auxiliary function to calculate per-thread max LSQ allocation limit.
306 * Depending on a policy, number of entries and possibly number of threads
307 * and threshold, this function calculates how many resources each thread
308 * can occupy at most.
309 */
957 /** The LSQ policy for SMT mode. */
958 SMTQueuePolicy lsqPolicy;
959
960 /** Auxiliary function to calculate per-thread max LSQ allocation limit.
961 * Depending on a policy, number of entries and possibly number of threads
962 * and threshold, this function calculates how many resources each thread
963 * can occupy at most.
964 */
310 static uint32_t maxLSQAllocation(SMTQueuePolicy pol, uint32_t entries,
311 uint32_t numThreads, uint32_t SMTThreshold) {
965 static uint32_t
966 maxLSQAllocation(SMTQueuePolicy pol, uint32_t entries,
967 uint32_t numThreads, uint32_t SMTThreshold)
968 {
312 if (pol == SMTQueuePolicy::Dynamic) {
313 return entries;
314 } else if (pol == SMTQueuePolicy::Partitioned) {
315 //@todo:make work if part_amt doesnt divide evenly.
316 return entries / numThreads;
317 } else if (pol == SMTQueuePolicy::Threshold) {
318 //Divide up by threshold amount
319 //@todo: Should threads check the max and the total

--- 21 unchanged lines hidden (view full) ---

341 std::vector<LSQUnit> thread;
342
343 /** Number of Threads. */
344 ThreadID numThreads;
345};
346
347template <class Impl>
348Fault
969 if (pol == SMTQueuePolicy::Dynamic) {
970 return entries;
971 } else if (pol == SMTQueuePolicy::Partitioned) {
972 //@todo:make work if part_amt doesnt divide evenly.
973 return entries / numThreads;
974 } else if (pol == SMTQueuePolicy::Threshold) {
975 //Divide up by threshold amount
976 //@todo: Should threads check the max and the total

--- 21 unchanged lines hidden (view full) ---

998 std::vector<LSQUnit> thread;
999
1000 /** Number of Threads. */
1001 ThreadID numThreads;
1002};
1003
1004template <class Impl>
1005Fault
349LSQ<Impl>::read(const RequestPtr &req,
350 RequestPtr &sreqLow, RequestPtr &sreqHigh,
351 int load_idx)
1006LSQ<Impl>::read(LSQRequest* req, int load_idx)
352{
1007{
353 ThreadID tid = cpu->contextToThread(req->contextId());
1008 ThreadID tid = cpu->contextToThread(req->request()->contextId());
354
1009
355 return thread[tid].read(req, sreqLow, sreqHigh, load_idx);
1010 return thread.at(tid).read(req, load_idx);
356}
357
358template <class Impl>
359Fault
1011}
1012
1013template <class Impl>
1014Fault
360LSQ<Impl>::write(const RequestPtr &req,
361 const RequestPtr &sreqLow, const RequestPtr &sreqHigh,
362 uint8_t *data, int store_idx)
1015LSQ<Impl>::write(LSQRequest* req, uint8_t *data, int store_idx)
363{
1016{
364 ThreadID tid = cpu->contextToThread(req->contextId());
1017 ThreadID tid = cpu->contextToThread(req->request()->contextId());
365
1018
366 return thread[tid].write(req, sreqLow, sreqHigh, data, store_idx);
1019 return thread.at(tid).write(req, data, store_idx);
367}
368
369#endif // __CPU_O3_LSQ_HH__
1020}
1021
1022#endif // __CPU_O3_LSQ_HH__