2 * Copyright (c) 2011-2012, 2014, 2017-2018 ARM Limited
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
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
11 * terms below provided that you ensure that this notice is replicated
12 * unmodified and in its entirety in all distributions of the software,
13 * modified or unmodified, in source code or in binary form.
15 * Copyright (c) 2005-2006 The Regents of The University of Michigan
16 * All rights reserved.
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 * Authors: Korey Sewell
44 #ifndef __CPU_O3_LSQ_IMPL_HH__
45 #define __CPU_O3_LSQ_IMPL_HH__
51 #include "base/logging.hh"
52 #include "cpu/o3/lsq.hh"
53 #include "debug/Drain.hh"
54 #include "debug/Fetch.hh"
55 #include "debug/LSQ.hh"
56 #include "debug/Writeback.hh"
57 #include "params/DerivO3CPU.hh"
62 LSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params)
63 : cpu(cpu_ptr), iewStage(iew_ptr),
65 cacheStorePorts(params->cacheStorePorts), usedStorePorts(0),
66 cacheLoadPorts(params->cacheLoadPorts), usedLoadPorts(0),
67 lsqPolicy(params->smtLSQPolicy),
68 LQEntries(params->LQEntries),
69 SQEntries(params->SQEntries),
70 maxLQEntries(maxLSQAllocation(lsqPolicy, LQEntries, params->numThreads,
71 params->smtLSQThreshold)),
72 maxSQEntries(maxLSQAllocation(lsqPolicy, SQEntries, params->numThreads,
73 params->smtLSQThreshold)),
74 numThreads(params->numThreads)
76 assert(numThreads > 0 && numThreads <= Impl::MaxThreads);
78 //**********************************************/
79 //************ Handle SMT Parameters ***********/
80 //**********************************************/
82 /* Run SMT olicy checks. */
83 if (lsqPolicy == SMTQueuePolicy::Dynamic) {
84 DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n");
85 } else if (lsqPolicy == SMTQueuePolicy::Partitioned) {
86 DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: "
87 "%i entries per LQ | %i entries per SQ\n",
88 maxLQEntries,maxSQEntries);
89 } else if (lsqPolicy == SMTQueuePolicy::Threshold) {
91 assert(params->smtLSQThreshold > params->LQEntries);
92 assert(params->smtLSQThreshold > params->SQEntries);
94 DPRINTF(LSQ, "LSQ sharing policy set to Threshold: "
95 "%i entries per LQ | %i entries per SQ\n",
96 maxLQEntries,maxSQEntries);
98 panic("Invalid LSQ sharing policy. Options are: Dynamic, "
99 "Partitioned, Threshold");
102 thread.reserve(numThreads);
103 for (ThreadID tid = 0; tid < numThreads; tid++) {
104 thread.emplace_back(maxLQEntries, maxSQEntries);
105 thread[tid].init(cpu, iew_ptr, params, this, tid);
106 thread[tid].setDcachePort(&cpu_ptr->getDataPort());
113 LSQ<Impl>::name() const
115 return iewStage->name() + ".lsq";
120 LSQ<Impl>::regStats()
123 for (ThreadID tid = 0; tid < numThreads; tid++) {
124 thread[tid].regStats();
130 LSQ<Impl>::setActiveThreads(list<ThreadID> *at_ptr)
132 activeThreads = at_ptr;
133 assert(activeThreads != 0);
136 template <class Impl>
138 LSQ<Impl>::drainSanityCheck() const
142 for (ThreadID tid = 0; tid < numThreads; tid++)
143 thread[tid].drainSanityCheck();
146 template <class Impl>
148 LSQ<Impl>::isDrained() const
153 DPRINTF(Drain, "Not drained, LQ not empty.\n");
158 DPRINTF(Drain, "Not drained, SQ not empty.\n");
165 template <class Impl>
167 LSQ<Impl>::takeOverFrom()
170 _cacheBlocked = false;
172 for (ThreadID tid = 0; tid < numThreads; tid++) {
173 thread[tid].takeOverFrom();
177 template <class Impl>
181 // Re-issue loads which got blocked on the per-cycle load ports limit.
182 if (usedLoadPorts == cacheLoadPorts && !_cacheBlocked)
183 iewStage->cacheUnblocked();
191 LSQ<Impl>::cacheBlocked() const
193 return _cacheBlocked;
198 LSQ<Impl>::cacheBlocked(bool v)
205 LSQ<Impl>::cachePortAvailable(bool is_load) const
209 ret = usedLoadPorts < cacheLoadPorts;
211 ret = usedStorePorts < cacheStorePorts;
218 LSQ<Impl>::cachePortBusy(bool is_load)
220 assert(cachePortAvailable(is_load));
230 LSQ<Impl>::insertLoad(const DynInstPtr &load_inst)
232 ThreadID tid = load_inst->threadNumber;
234 thread[tid].insertLoad(load_inst);
239 LSQ<Impl>::insertStore(const DynInstPtr &store_inst)
241 ThreadID tid = store_inst->threadNumber;
243 thread[tid].insertStore(store_inst);
248 LSQ<Impl>::executeLoad(const DynInstPtr &inst)
250 ThreadID tid = inst->threadNumber;
252 return thread[tid].executeLoad(inst);
257 LSQ<Impl>::executeStore(const DynInstPtr &inst)
259 ThreadID tid = inst->threadNumber;
261 return thread[tid].executeStore(inst);
266 LSQ<Impl>::writebackStores()
268 list<ThreadID>::iterator threads = activeThreads->begin();
269 list<ThreadID>::iterator end = activeThreads->end();
271 while (threads != end) {
272 ThreadID tid = *threads++;
274 if (numStoresToWB(tid) > 0) {
275 DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores "
276 "available for Writeback.\n", tid, numStoresToWB(tid));
279 thread[tid].writebackStores();
285 LSQ<Impl>::violation()
287 /* Answers: Does Anybody Have a Violation?*/
288 list<ThreadID>::iterator threads = activeThreads->begin();
289 list<ThreadID>::iterator end = activeThreads->end();
291 while (threads != end) {
292 ThreadID tid = *threads++;
294 if (thread[tid].violation())
301 template <class Impl>
303 LSQ<Impl>::recvReqRetry()
305 iewStage->cacheUnblocked();
308 for (ThreadID tid : *activeThreads) {
309 thread[tid].recvRetry();
313 template <class Impl>
315 LSQ<Impl>::completeDataAccess(PacketPtr pkt)
317 auto senderState = dynamic_cast<LSQSenderState*>(pkt->senderState);
318 thread[cpu->contextToThread(senderState->contextId())]
319 .completeDataAccess(pkt);
322 template <class Impl>
324 LSQ<Impl>::recvTimingResp(PacketPtr pkt)
327 DPRINTF(LSQ, "Got error packet back for address: %#X\n",
330 auto senderState = dynamic_cast<LSQSenderState*>(pkt->senderState);
331 panic_if(!senderState, "Got packet back with unknown sender state\n");
333 thread[cpu->contextToThread(senderState->contextId())].recvTimingResp(pkt);
335 if (pkt->isInvalidate()) {
336 // This response also contains an invalidate; e.g. this can be the case
337 // if cmd is ReadRespWithInvalidate.
339 // The calling order between completeDataAccess and checkSnoop matters.
340 // By calling checkSnoop after completeDataAccess, we ensure that the
341 // fault set by checkSnoop is not lost. Calling writeback (more
342 // specifically inst->completeAcc) in completeDataAccess overwrites
343 // fault, and in case this instruction requires squashing (as
344 // determined by checkSnoop), the ReExec fault set by checkSnoop would
345 // be lost otherwise.
347 DPRINTF(LSQ, "received invalidation with response for addr:%#x\n",
350 for (ThreadID tid = 0; tid < numThreads; tid++) {
351 thread[tid].checkSnoop(pkt);
354 // Update the LSQRequest state (this may delete the request)
355 senderState->request()->packetReplied();
360 template <class Impl>
362 LSQ<Impl>::recvTimingSnoopReq(PacketPtr pkt)
364 DPRINTF(LSQ, "received pkt for addr:%#x %s\n", pkt->getAddr(),
368 if (pkt->isInvalidate()) {
369 DPRINTF(LSQ, "received invalidation for addr:%#x\n",
371 for (ThreadID tid = 0; tid < numThreads; tid++) {
372 thread[tid].checkSnoop(pkt);
379 LSQ<Impl>::getCount()
383 list<ThreadID>::iterator threads = activeThreads->begin();
384 list<ThreadID>::iterator end = activeThreads->end();
386 while (threads != end) {
387 ThreadID tid = *threads++;
389 total += getCount(tid);
397 LSQ<Impl>::numLoads()
401 list<ThreadID>::iterator threads = activeThreads->begin();
402 list<ThreadID>::iterator end = activeThreads->end();
404 while (threads != end) {
405 ThreadID tid = *threads++;
407 total += numLoads(tid);
415 LSQ<Impl>::numStores()
419 list<ThreadID>::iterator threads = activeThreads->begin();
420 list<ThreadID>::iterator end = activeThreads->end();
422 while (threads != end) {
423 ThreadID tid = *threads++;
425 total += thread[tid].numStores();
433 LSQ<Impl>::numFreeLoadEntries()
437 list<ThreadID>::iterator threads = activeThreads->begin();
438 list<ThreadID>::iterator end = activeThreads->end();
440 while (threads != end) {
441 ThreadID tid = *threads++;
443 total += thread[tid].numFreeLoadEntries();
451 LSQ<Impl>::numFreeStoreEntries()
455 list<ThreadID>::iterator threads = activeThreads->begin();
456 list<ThreadID>::iterator end = activeThreads->end();
458 while (threads != end) {
459 ThreadID tid = *threads++;
461 total += thread[tid].numFreeStoreEntries();
469 LSQ<Impl>::numFreeLoadEntries(ThreadID tid)
471 return thread[tid].numFreeLoadEntries();
476 LSQ<Impl>::numFreeStoreEntries(ThreadID tid)
478 return thread[tid].numFreeStoreEntries();
485 list<ThreadID>::iterator threads = activeThreads->begin();
486 list<ThreadID>::iterator end = activeThreads->end();
488 while (threads != end) {
489 ThreadID tid = *threads++;
491 if (!(thread[tid].lqFull() || thread[tid].sqFull()))
500 LSQ<Impl>::isFull(ThreadID tid)
502 //@todo: Change to Calculate All Entries for
504 if (lsqPolicy == SMTQueuePolicy::Dynamic)
507 return thread[tid].lqFull() || thread[tid].sqFull();
512 LSQ<Impl>::isEmpty() const
514 return lqEmpty() && sqEmpty();
519 LSQ<Impl>::lqEmpty() const
521 list<ThreadID>::const_iterator threads = activeThreads->begin();
522 list<ThreadID>::const_iterator end = activeThreads->end();
524 while (threads != end) {
525 ThreadID tid = *threads++;
527 if (!thread[tid].lqEmpty())
536 LSQ<Impl>::sqEmpty() const
538 list<ThreadID>::const_iterator threads = activeThreads->begin();
539 list<ThreadID>::const_iterator end = activeThreads->end();
541 while (threads != end) {
542 ThreadID tid = *threads++;
544 if (!thread[tid].sqEmpty())
555 list<ThreadID>::iterator threads = activeThreads->begin();
556 list<ThreadID>::iterator end = activeThreads->end();
558 while (threads != end) {
559 ThreadID tid = *threads++;
561 if (!thread[tid].lqFull())
570 LSQ<Impl>::lqFull(ThreadID tid)
572 //@todo: Change to Calculate All Entries for
574 if (lsqPolicy == SMTQueuePolicy::Dynamic)
577 return thread[tid].lqFull();
584 list<ThreadID>::iterator threads = activeThreads->begin();
585 list<ThreadID>::iterator end = activeThreads->end();
587 while (threads != end) {
588 ThreadID tid = *threads++;
599 LSQ<Impl>::sqFull(ThreadID tid)
601 //@todo: Change to Calculate All Entries for
603 if (lsqPolicy == SMTQueuePolicy::Dynamic)
606 return thread[tid].sqFull();
611 LSQ<Impl>::isStalled()
613 list<ThreadID>::iterator threads = activeThreads->begin();
614 list<ThreadID>::iterator end = activeThreads->end();
616 while (threads != end) {
617 ThreadID tid = *threads++;
619 if (!thread[tid].isStalled())
628 LSQ<Impl>::isStalled(ThreadID tid)
630 if (lsqPolicy == SMTQueuePolicy::Dynamic)
633 return thread[tid].isStalled();
638 LSQ<Impl>::hasStoresToWB()
640 list<ThreadID>::iterator threads = activeThreads->begin();
641 list<ThreadID>::iterator end = activeThreads->end();
643 while (threads != end) {
644 ThreadID tid = *threads++;
646 if (hasStoresToWB(tid))
657 list<ThreadID>::iterator threads = activeThreads->begin();
658 list<ThreadID>::iterator end = activeThreads->end();
660 while (threads != end) {
661 ThreadID tid = *threads++;
672 LSQ<Impl>::dumpInsts() const
674 list<ThreadID>::const_iterator threads = activeThreads->begin();
675 list<ThreadID>::const_iterator end = activeThreads->end();
677 while (threads != end) {
678 ThreadID tid = *threads++;
680 thread[tid].dumpInsts();
685 addrBlockOffset(Addr addr, unsigned int block_size)
687 return addr & (block_size - 1);
691 addrBlockAlign(Addr addr, uint64_t block_size)
693 return addr & ~(block_size - 1);
697 transferNeedsBurst(Addr addr, uint64_t size, uint64_t block_size)
699 return (addrBlockOffset(addr, block_size) + size) > block_size;
704 LSQ<Impl>::pushRequest(const DynInstPtr& inst, bool isLoad, uint8_t *data,
705 unsigned int size, Addr addr, Request::Flags flags,
706 uint64_t *res, AtomicOpFunctor *amo_op)
708 // This comming request can be either load, store or atomic.
709 // Atomic request has a corresponding pointer to its atomic memory
711 bool isAtomic M5_VAR_USED = !isLoad && amo_op;
713 ThreadID tid = cpu->contextToThread(inst->contextId());
714 auto cacheLineSize = cpu->cacheLineSize();
715 bool needs_burst = transferNeedsBurst(addr, size, cacheLineSize);
716 LSQRequest* req = nullptr;
718 // Atomic requests that access data across cache line boundary are
719 // currently not allowed since the cache does not guarantee corresponding
720 // atomic memory operations to be executed atomically across a cache line.
721 // For ISAs such as x86 that supports cross-cache-line atomic instructions,
722 // the cache needs to be modified to perform atomic update to both cache
723 // lines. For now, such cross-line update is not supported.
724 assert(!isAtomic || (isAtomic && !needs_burst));
726 if (inst->translationStarted()) {
727 req = inst->savedReq;
731 req = new SplitDataRequest(&thread[tid], inst, isLoad, addr,
732 size, flags, data, res);
734 req = new SingleDataRequest(&thread[tid], inst, isLoad, addr,
735 size, flags, data, res, amo_op);
739 req->taskId(cpu->taskId());
741 req->initiateTranslation();
744 /* This is the place were instructions get the effAddr. */
745 if (req->isTranslationComplete()) {
746 if (inst->getFault() == NoFault) {
747 inst->effAddr = req->getVaddr();
748 inst->effSize = size;
749 inst->effAddrValid(true);
752 inst->reqToVerify = std::make_shared<Request>(*req->request());
755 inst->getFault() = cpu->read(req, inst->lqIdx);
757 inst->getFault() = cpu->write(req, data, inst->sqIdx);
759 // Commit will have to clean up whatever happened. Set this
760 // instruction as executed.
766 inst->traceData->setMem(addr, size, flags);
768 return inst->getFault();
773 LSQ<Impl>::SingleDataRequest::finish(const Fault &fault, const RequestPtr &req,
774 ThreadContext* tc, BaseTLB::Mode mode)
776 _fault.push_back(fault);
777 numInTranslationFragments = 0;
778 numTranslatedFragments = 1;
779 /* If the instruction has been squahsed, let the request know
780 * as it may have to self-destruct. */
781 if (_inst->isSquashed()) {
782 this->squashTranslation();
784 _inst->strictlyOrdered(req->isStrictlyOrdered());
786 flags.set(Flag::TranslationFinished);
787 if (fault == NoFault) {
788 _inst->physEffAddr = req->getPaddr();
789 _inst->memReqFlags = req->getFlags();
790 if (req->isCondSwap()) {
792 req->setExtraData(*_res);
794 setState(State::Request);
796 setState(State::Fault);
799 LSQRequest::_inst->fault = fault;
800 LSQRequest::_inst->translationCompleted(true);
806 LSQ<Impl>::SplitDataRequest::finish(const Fault &fault, const RequestPtr &req,
807 ThreadContext* tc, BaseTLB::Mode mode)
809 _fault.push_back(fault);
810 assert(req == _requests[numTranslatedFragments] || this->isDelayed());
812 numInTranslationFragments--;
813 numTranslatedFragments++;
815 mainReq->setFlags(req->getFlags());
817 if (numTranslatedFragments == _requests.size()) {
818 if (_inst->isSquashed()) {
819 this->squashTranslation();
821 _inst->strictlyOrdered(mainReq->isStrictlyOrdered());
822 flags.set(Flag::TranslationFinished);
823 auto fault_it = _fault.begin();
824 /* Ffwd to the first NoFault. */
825 while (fault_it != _fault.end() && *fault_it == NoFault)
827 /* If none of the fragments faulted: */
828 if (fault_it == _fault.end()) {
829 _inst->physEffAddr = request(0)->getPaddr();
831 _inst->memReqFlags = mainReq->getFlags();
832 if (mainReq->isCondSwap()) {
834 mainReq->setExtraData(*_res);
836 setState(State::Request);
837 _inst->fault = NoFault;
839 setState(State::Fault);
840 _inst->fault = *fault_it;
842 _inst->translationCompleted(true);
849 LSQ<Impl>::SingleDataRequest::initiateTranslation()
851 _inst->translationStarted(true);
852 setState(State::Translation);
853 flags.set(Flag::TranslationStarted);
855 _inst->savedReq = this;
856 sendFragmentToTranslation(0);
858 if (isTranslationComplete()) {
864 LSQ<Impl>::SplitDataRequest::mainPacket()
871 LSQ<Impl>::SplitDataRequest::mainRequest()
878 LSQ<Impl>::SplitDataRequest::initiateTranslation()
880 _inst->translationStarted(true);
881 setState(State::Translation);
882 flags.set(Flag::TranslationStarted);
884 unsigned int cacheLineSize = _port.cacheLineSize();
885 Addr base_addr = _addr;
886 Addr next_addr = addrBlockAlign(_addr + cacheLineSize, cacheLineSize);
887 Addr final_addr = addrBlockAlign(_addr + _size, cacheLineSize);
888 uint32_t size_so_far = 0;
890 mainReq = std::make_shared<Request>(_inst->getASID(), base_addr,
891 _size, _flags, _inst->masterId(),
892 _inst->instAddr(), _inst->contextId());
894 // Paddr is not used in mainReq. However, we will accumulate the flags
895 // from the sub requests into mainReq by calling setFlags() in finish().
896 // setFlags() assumes that paddr is set so flip the paddr valid bit here to
897 // avoid a potential assert in setFlags() when we call it from finish().
898 mainReq->setPaddr(0);
900 /* Get the pre-fix, possibly unaligned. */
901 _requests.push_back(std::make_shared<Request>(_inst->getASID(), base_addr,
902 next_addr - base_addr, _flags, _inst->masterId(),
903 _inst->instAddr(), _inst->contextId()));
904 size_so_far = next_addr - base_addr;
906 /* We are block aligned now, reading whole blocks. */
907 base_addr = next_addr;
908 while (base_addr != final_addr) {
909 _requests.push_back(std::make_shared<Request>(_inst->getASID(),
910 base_addr, cacheLineSize, _flags, _inst->masterId(),
911 _inst->instAddr(), _inst->contextId()));
912 size_so_far += cacheLineSize;
913 base_addr += cacheLineSize;
916 /* Deal with the tail. */
917 if (size_so_far < _size) {
918 _requests.push_back(std::make_shared<Request>(_inst->getASID(),
919 base_addr, _size - size_so_far, _flags, _inst->masterId(),
920 _inst->instAddr(), _inst->contextId()));
923 /* Setup the requests and send them to translation. */
924 for (auto& r: _requests) {
925 r->setReqInstSeqNum(_inst->seqNum);
928 this->_inst->savedReq = this;
929 numInTranslationFragments = 0;
930 numTranslatedFragments = 0;
932 for (uint32_t i = 0; i < _requests.size(); i++) {
933 sendFragmentToTranslation(i);
939 LSQ<Impl>::LSQRequest::sendFragmentToTranslation(int i)
941 numInTranslationFragments++;
942 _port.dTLB()->translateTiming(
944 this->_inst->thread->getTC(), this,
945 this->isLoad() ? BaseTLB::Read : BaseTLB::Write);
950 LSQ<Impl>::SingleDataRequest::recvTimingResp(PacketPtr pkt)
952 assert(_numOutstandingPackets == 1);
953 auto state = dynamic_cast<LSQSenderState*>(pkt->senderState);
954 setState(State::Complete);
955 flags.set(Flag::Complete);
956 state->outstanding--;
957 assert(pkt == _packets.front());
958 _port.completeDataAccess(pkt);
964 LSQ<Impl>::SplitDataRequest::recvTimingResp(PacketPtr pkt)
966 auto state = dynamic_cast<LSQSenderState*>(pkt->senderState);
968 while (pktIdx < _packets.size() && pkt != _packets[pktIdx])
970 assert(pktIdx < _packets.size());
971 assert(pkt->req == _requests[pktIdx]);
972 assert(pkt == _packets[pktIdx]);
973 numReceivedPackets++;
974 state->outstanding--;
975 if (numReceivedPackets == _packets.size()) {
976 setState(State::Complete);
977 flags.set(Flag::Complete);
978 /* Assemble packets. */
979 PacketPtr resp = isLoad()
980 ? Packet::createRead(mainReq)
981 : Packet::createWrite(mainReq);
983 resp->dataStatic(_inst->memData);
985 resp->dataStatic(_data);
986 resp->senderState = _senderState;
987 _port.completeDataAccess(resp);
995 LSQ<Impl>::SingleDataRequest::buildPackets()
997 assert(_senderState);
998 /* Retries do not create new packets. */
999 if (_packets.size() == 0) {
1002 ? Packet::createRead(request())
1003 : Packet::createWrite(request()));
1004 _packets.back()->dataStatic(_inst->memData);
1005 _packets.back()->senderState = _senderState;
1007 assert(_packets.size() == 1);
1010 template<class Impl>
1012 LSQ<Impl>::SplitDataRequest::buildPackets()
1015 ptrdiff_t offset = 0;
1016 if (_packets.size() == 0) {
1019 _mainPacket = Packet::createRead(mainReq);
1020 _mainPacket->dataStatic(_inst->memData);
1022 for (auto& r: _requests) {
1023 PacketPtr pkt = isLoad() ? Packet::createRead(r)
1024 : Packet::createWrite(r);
1026 pkt->dataStatic(_inst->memData + offset);
1028 uint8_t* req_data = new uint8_t[r->getSize()];
1029 std::memcpy(req_data,
1030 _inst->memData + offset,
1032 pkt->dataDynamic(req_data);
1034 offset += r->getSize();
1035 pkt->senderState = _senderState;
1036 _packets.push_back(pkt);
1039 assert(_packets.size() == _requests.size());
1042 template<class Impl>
1044 LSQ<Impl>::SingleDataRequest::sendPacketToCache()
1046 assert(_numOutstandingPackets == 0);
1047 if (lsqUnit()->trySendPacket(isLoad(), _packets.at(0)))
1048 _numOutstandingPackets = 1;
1051 template<class Impl>
1053 LSQ<Impl>::SplitDataRequest::sendPacketToCache()
1055 /* Try to send the packets. */
1056 while (numReceivedPackets + _numOutstandingPackets < _packets.size() &&
1057 lsqUnit()->trySendPacket(isLoad(),
1058 _packets.at(numReceivedPackets + _numOutstandingPackets))) {
1059 _numOutstandingPackets++;
1063 template<class Impl>
1065 LSQ<Impl>::SingleDataRequest::handleIprWrite(ThreadContext *thread,
1068 TheISA::handleIprWrite(thread, pkt);
1071 template<class Impl>
1073 LSQ<Impl>::SplitDataRequest::handleIprWrite(ThreadContext *thread,
1076 unsigned offset = 0;
1077 for (auto r: _requests) {
1078 PacketPtr pkt = new Packet(r, MemCmd::WriteReq);
1079 pkt->dataStatic(mainPkt->getPtr<uint8_t>() + offset);
1080 TheISA::handleIprWrite(thread, pkt);
1081 offset += r->getSize();
1086 template<class Impl>
1088 LSQ<Impl>::SingleDataRequest::handleIprRead(ThreadContext *thread,
1091 return TheISA::handleIprRead(thread, pkt);
1094 template<class Impl>
1096 LSQ<Impl>::SplitDataRequest::handleIprRead(ThreadContext *thread,
1100 unsigned offset = 0;
1102 for (auto r: _requests) {
1103 PacketPtr pkt = new Packet(r, MemCmd::ReadReq);
1104 pkt->dataStatic(mainPkt->getPtr<uint8_t>() + offset);
1105 Cycles d = TheISA::handleIprRead(thread, pkt);
1108 offset += r->getSize();
1114 template<class Impl>
1116 LSQ<Impl>::SingleDataRequest::isCacheBlockHit(Addr blockAddr, Addr blockMask)
1118 return ( (LSQRequest::_requests[0]->getPaddr() & blockMask) == blockAddr);
1121 template<class Impl>
1123 LSQ<Impl>::SplitDataRequest::isCacheBlockHit(Addr blockAddr, Addr blockMask)
1125 bool is_hit = false;
1126 for (auto &r: _requests) {
1127 if ((r->getPaddr() & blockMask) == blockAddr) {
1135 #endif//__CPU_O3_LSQ_IMPL_HH__