2 * Copyright (c) 2013-2014 ARM Limited
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.
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.
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.
37 * Authors: Andrew Bardsley
40 #include "cpu/minor/lsq.hh"
45 #include "arch/locked_mem.hh"
46 #include "arch/mmapped_ipr.hh"
47 #include "cpu/minor/cpu.hh"
48 #include "cpu/minor/exec_context.hh"
49 #include "cpu/minor/execute.hh"
50 #include "cpu/minor/pipeline.hh"
51 #include "debug/Activity.hh"
52 #include "debug/MinorMem.hh"
57 /** Returns the offset of addr into an aligned a block of size block_size */
59 addrBlockOffset(Addr addr
, unsigned int block_size
)
61 return addr
& (block_size
- 1);
64 /** Returns true if the given [addr .. addr+size-1] transfer needs to be
65 * fragmented across a block size of block_size */
67 transferNeedsBurst(Addr addr
, unsigned int size
, unsigned int block_size
)
69 return (addrBlockOffset(addr
, block_size
) + size
) > block_size
;
72 LSQ::LSQRequest::LSQRequest(LSQ
&port_
, MinorDynInstPtr inst_
, bool isLoad_
,
73 PacketDataPtr data_
, uint64_t *res_
) :
84 issuedToMemory(false),
88 LSQ::AddrRangeCoverage
89 LSQ::LSQRequest::containsAddrRangeOf(
90 Addr req1_addr
, unsigned int req1_size
,
91 Addr req2_addr
, unsigned int req2_size
)
93 /* 'end' here means the address of the byte just past the request
95 Addr req2_end_addr
= req2_addr
+ req2_size
;
96 Addr req1_end_addr
= req1_addr
+ req1_size
;
98 AddrRangeCoverage ret
;
100 if (req1_addr
> req2_end_addr
|| req1_end_addr
< req2_addr
)
101 ret
= NoAddrRangeCoverage
;
102 else if (req1_addr
<= req2_addr
&& req1_end_addr
>= req2_end_addr
)
103 ret
= FullAddrRangeCoverage
;
105 ret
= PartialAddrRangeCoverage
;
110 LSQ::AddrRangeCoverage
111 LSQ::LSQRequest::containsAddrRangeOf(LSQRequestPtr other_request
)
113 return containsAddrRangeOf(request
.getPaddr(), request
.getSize(),
114 other_request
->request
.getPaddr(), other_request
->request
.getSize());
118 LSQ::LSQRequest::isBarrier()
120 return inst
->isInst() && inst
->staticInst
->isMemBarrier();
124 LSQ::LSQRequest::needsToBeSentToStoreBuffer()
126 return state
== StoreToStoreBuffer
;
130 LSQ::LSQRequest::setState(LSQRequestState new_state
)
132 DPRINTFS(MinorMem
, (&port
), "Setting state from %d to %d for request:"
133 " %s\n", state
, new_state
, *inst
);
138 LSQ::LSQRequest::isComplete() const
140 /* @todo, There is currently only one 'completed' state. This
141 * may not be a good choice */
142 return state
== Complete
;
146 LSQ::LSQRequest::reportData(std::ostream
&os
) const
148 os
<< (isLoad
? 'R' : 'W') << ';';
149 inst
->reportData(os
);
154 operator <<(std::ostream
&os
, LSQ::AddrRangeCoverage coverage
)
157 case LSQ::PartialAddrRangeCoverage
:
158 os
<< "PartialAddrRangeCoverage";
160 case LSQ::FullAddrRangeCoverage
:
161 os
<< "FullAddrRangeCoverage";
163 case LSQ::NoAddrRangeCoverage
:
164 os
<< "NoAddrRangeCoverage";
167 os
<< "AddrRangeCoverage-" << static_cast<int>(coverage
);
174 operator <<(std::ostream
&os
, LSQ::LSQRequest::LSQRequestState state
)
177 case LSQ::LSQRequest::NotIssued
:
180 case LSQ::LSQRequest::InTranslation
:
181 os
<< "InTranslation";
183 case LSQ::LSQRequest::Translated
:
186 case LSQ::LSQRequest::Failed
:
189 case LSQ::LSQRequest::RequestIssuing
:
190 os
<< "RequestIssuing";
192 case LSQ::LSQRequest::StoreToStoreBuffer
:
193 os
<< "StoreToStoreBuffer";
195 case LSQ::LSQRequest::StoreInStoreBuffer
:
196 os
<< "StoreInStoreBuffer";
198 case LSQ::LSQRequest::StoreBufferIssuing
:
199 os
<< "StoreBufferIssuing";
201 case LSQ::LSQRequest::RequestNeedsRetry
:
202 os
<< "RequestNeedsRetry";
204 case LSQ::LSQRequest::StoreBufferNeedsRetry
:
205 os
<< "StoreBufferNeedsRetry";
207 case LSQ::LSQRequest::Complete
:
211 os
<< "LSQRequestState-" << static_cast<int>(state
);
218 LSQ::clearMemBarrier(MinorDynInstPtr inst
)
220 bool is_last_barrier
=
221 inst
->id
.execSeqNum
>= lastMemBarrier
[inst
->id
.threadId
];
223 DPRINTF(MinorMem
, "Moving %s barrier out of store buffer inst: %s\n",
224 (is_last_barrier
? "last" : "a"), *inst
);
227 lastMemBarrier
[inst
->id
.threadId
] = 0;
231 LSQ::SingleDataRequest::finish(const Fault
&fault_
, RequestPtr request_
,
232 ThreadContext
*tc
, BaseTLB::Mode mode
)
236 port
.numAccessesInDTLB
--;
238 DPRINTFS(MinorMem
, (&port
), "Received translation response for"
239 " request: %s\n", *inst
);
243 setState(Translated
);
244 port
.tryToSendToTransfers(this);
246 /* Let's try and wake up the processor for the next cycle */
247 port
.cpu
.wakeupOnEvent(Pipeline::ExecuteStageId
);
251 LSQ::SingleDataRequest::startAddrTranslation()
253 ThreadContext
*thread
= port
.cpu
.getContext(
256 port
.numAccessesInDTLB
++;
258 setState(LSQ::LSQRequest::InTranslation
);
260 DPRINTFS(MinorMem
, (&port
), "Submitting DTLB request\n");
261 /* Submit the translation request. The response will come through
262 * finish/markDelayed on the LSQRequest as it bears the Translation
264 thread
->getDTBPtr()->translateTiming(
265 &request
, thread
, this, (isLoad
? BaseTLB::Read
: BaseTLB::Write
));
269 LSQ::SingleDataRequest::retireResponse(PacketPtr packet_
)
271 DPRINTFS(MinorMem
, (&port
), "Retiring packet\n");
273 packetInFlight
= false;
278 LSQ::SplitDataRequest::finish(const Fault
&fault_
, RequestPtr request_
,
279 ThreadContext
*tc
, BaseTLB::Mode mode
)
283 port
.numAccessesInDTLB
--;
285 unsigned int M5_VAR_USED expected_fragment_index
=
286 numTranslatedFragments
;
288 numInTranslationFragments
--;
289 numTranslatedFragments
++;
291 DPRINTFS(MinorMem
, (&port
), "Received translation response for fragment"
292 " %d of request: %s\n", expected_fragment_index
, *inst
);
294 assert(request_
== fragmentRequests
[expected_fragment_index
]);
296 /* Wake up next cycle to get things going again in case the
297 * tryToSendToTransfers does take */
298 port
.cpu
.wakeupOnEvent(Pipeline::ExecuteStageId
);
300 if (fault
!= NoFault
) {
301 /* tryToSendToTransfers will handle the fault */
303 DPRINTFS(MinorMem
, (&port
), "Faulting translation for fragment:"
304 " %d of request: %s\n",
305 expected_fragment_index
, *inst
);
307 setState(Translated
);
308 port
.tryToSendToTransfers(this);
309 } else if (numTranslatedFragments
== numFragments
) {
310 makeFragmentPackets();
312 setState(Translated
);
313 port
.tryToSendToTransfers(this);
315 /* Avoid calling translateTiming from within ::finish */
316 assert(!translationEvent
.scheduled());
317 port
.cpu
.schedule(translationEvent
, curTick());
321 LSQ::SplitDataRequest::SplitDataRequest(LSQ
&port_
, MinorDynInstPtr inst_
,
322 bool isLoad_
, PacketDataPtr data_
, uint64_t *res_
) :
323 LSQRequest(port_
, inst_
, isLoad_
, data_
, res_
),
324 translationEvent([this]{ sendNextFragmentToTranslation(); },
327 numInTranslationFragments(0),
328 numTranslatedFragments(0),
329 numIssuedFragments(0),
330 numRetiredFragments(0),
334 /* Don't know how many elements are needed until the request is
335 * populated by the caller. */
338 LSQ::SplitDataRequest::~SplitDataRequest()
340 for (auto i
= fragmentRequests
.begin();
341 i
!= fragmentRequests
.end(); i
++)
346 for (auto i
= fragmentPackets
.begin();
347 i
!= fragmentPackets
.end(); i
++)
354 LSQ::SplitDataRequest::makeFragmentRequests()
356 Addr base_addr
= request
.getVaddr();
357 unsigned int whole_size
= request
.getSize();
358 unsigned int line_width
= port
.lineWidth
;
360 unsigned int fragment_size
;
363 /* Assume that this transfer is across potentially many block snap
366 * | _|________|________|________|___ |
367 * | |0| 1 | 2 | 3 | 4 | |
368 * | |_|________|________|________|___| |
371 * The first transfer (0) can be up to lineWidth in size.
372 * All the middle transfers (1-3) are lineWidth in size
373 * The last transfer (4) can be from zero to lineWidth - 1 in size
375 unsigned int first_fragment_offset
=
376 addrBlockOffset(base_addr
, line_width
);
377 unsigned int last_fragment_size
=
378 addrBlockOffset(base_addr
+ whole_size
, line_width
);
379 unsigned int first_fragment_size
=
380 line_width
- first_fragment_offset
;
382 unsigned int middle_fragments_total_size
=
383 whole_size
- (first_fragment_size
+ last_fragment_size
);
385 assert(addrBlockOffset(middle_fragments_total_size
, line_width
) == 0);
387 unsigned int middle_fragment_count
=
388 middle_fragments_total_size
/ line_width
;
390 numFragments
= 1 /* first */ + middle_fragment_count
+
391 (last_fragment_size
== 0 ? 0 : 1);
393 DPRINTFS(MinorMem
, (&port
), "Dividing transfer into %d fragmentRequests."
394 " First fragment size: %d Last fragment size: %d\n",
395 numFragments
, first_fragment_size
,
396 (last_fragment_size
== 0 ? line_width
: last_fragment_size
));
398 assert(((middle_fragment_count
* line_width
) +
399 first_fragment_size
+ last_fragment_size
) == whole_size
);
401 fragment_addr
= base_addr
;
402 fragment_size
= first_fragment_size
;
404 /* Just past the last address in the request */
405 Addr end_addr
= base_addr
+ whole_size
;
407 for (unsigned int fragment_index
= 0; fragment_index
< numFragments
;
410 bool M5_VAR_USED is_last_fragment
= false;
412 if (fragment_addr
== base_addr
) {
414 fragment_size
= first_fragment_size
;
416 if ((fragment_addr
+ line_width
) > end_addr
) {
417 /* Adjust size of last fragment */
418 fragment_size
= end_addr
- fragment_addr
;
419 is_last_fragment
= true;
421 /* Middle fragments */
422 fragment_size
= line_width
;
426 Request
*fragment
= new Request();
428 fragment
->setContext(request
.contextId());
429 fragment
->setVirt(0 /* asid */,
430 fragment_addr
, fragment_size
, request
.getFlags(),
434 DPRINTFS(MinorMem
, (&port
), "Generating fragment addr: 0x%x size: %d"
435 " (whole request addr: 0x%x size: %d) %s\n",
436 fragment_addr
, fragment_size
, base_addr
, whole_size
,
437 (is_last_fragment
? "last fragment" : ""));
439 fragment_addr
+= fragment_size
;
441 fragmentRequests
.push_back(fragment
);
446 LSQ::SplitDataRequest::makeFragmentPackets()
448 Addr base_addr
= request
.getVaddr();
450 DPRINTFS(MinorMem
, (&port
), "Making packets for request: %s\n", *inst
);
452 for (unsigned int fragment_index
= 0; fragment_index
< numFragments
;
455 Request
*fragment
= fragmentRequests
[fragment_index
];
457 DPRINTFS(MinorMem
, (&port
), "Making packet %d for request: %s"
459 fragment_index
, *inst
,
460 (fragment
->hasPaddr() ? "has paddr" : "no paddr"),
461 (fragment
->hasPaddr() ? fragment
->getPaddr() : 0));
463 Addr fragment_addr
= fragment
->getVaddr();
464 unsigned int fragment_size
= fragment
->getSize();
466 uint8_t *request_data
= NULL
;
469 /* Split data for Packets. Will become the property of the
470 * outgoing Packets */
471 request_data
= new uint8_t[fragment_size
];
472 std::memcpy(request_data
, data
+ (fragment_addr
- base_addr
),
476 assert(fragment
->hasPaddr());
478 PacketPtr fragment_packet
=
479 makePacketForRequest(*fragment
, isLoad
, this, request_data
);
481 fragmentPackets
.push_back(fragment_packet
);
482 /* Accumulate flags in parent request */
483 request
.setFlags(fragment
->getFlags());
486 /* Might as well make the overall/response packet here */
487 /* Get the physical address for the whole request/packet from the first
489 request
.setPaddr(fragmentRequests
[0]->getPaddr());
494 LSQ::SplitDataRequest::startAddrTranslation()
496 setState(LSQ::LSQRequest::InTranslation
);
498 makeFragmentRequests();
500 numInTranslationFragments
= 0;
501 numTranslatedFragments
= 0;
503 /* @todo, just do these in sequence for now with
506 * sendNextFragmentToTranslation ; translateTiming ; finish
507 * } while (numTranslatedFragments != numFragments);
510 /* Do first translation */
511 sendNextFragmentToTranslation();
515 LSQ::SplitDataRequest::getHeadPacket()
517 assert(numIssuedFragments
< numFragments
);
519 return fragmentPackets
[numIssuedFragments
];
523 LSQ::SplitDataRequest::stepToNextPacket()
525 assert(numIssuedFragments
< numFragments
);
527 numIssuedFragments
++;
531 LSQ::SplitDataRequest::retireResponse(PacketPtr response
)
533 assert(numRetiredFragments
< numFragments
);
535 DPRINTFS(MinorMem
, (&port
), "Retiring fragment addr: 0x%x size: %d"
536 " offset: 0x%x (retired fragment num: %d) %s\n",
537 response
->req
->getVaddr(), response
->req
->getSize(),
538 request
.getVaddr() - response
->req
->getVaddr(),
540 (fault
== NoFault
? "" : fault
->name()));
542 numRetiredFragments
++;
545 /* Skip because we already knew the request had faulted or been
547 DPRINTFS(MinorMem
, (&port
), "Skipping this fragment\n");
548 } else if (response
->isError()) {
549 /* Mark up the error and leave to execute to handle it */
550 DPRINTFS(MinorMem
, (&port
), "Fragment has an error, skipping\n");
552 packet
->copyError(response
);
556 /* For a split transfer, a Packet must be constructed
557 * to contain all returning data. This is that packet's
559 data
= new uint8_t[request
.getSize()];
562 /* Populate the portion of the overall response data represented
563 * by the response fragment */
565 data
+ (response
->req
->getVaddr() - request
.getVaddr()),
566 response
->getConstPtr
<uint8_t>(),
567 response
->req
->getSize());
571 /* Complete early if we're skipping are no more in-flight accesses */
572 if (skipped
&& !hasPacketsInMemSystem()) {
573 DPRINTFS(MinorMem
, (&port
), "Completed skipped burst\n");
575 if (packet
->needsResponse())
576 packet
->makeResponse();
579 if (numRetiredFragments
== numFragments
)
582 if (!skipped
&& isComplete()) {
583 DPRINTFS(MinorMem
, (&port
), "Completed burst %d\n", packet
!= NULL
);
585 DPRINTFS(MinorMem
, (&port
), "Retired packet isRead: %d isWrite: %d"
586 " needsResponse: %d packetSize: %s requestSize: %s responseSize:"
587 " %s\n", packet
->isRead(), packet
->isWrite(),
588 packet
->needsResponse(), packet
->getSize(), request
.getSize(),
589 response
->getSize());
591 /* A request can become complete by several paths, this is a sanity
592 * check to make sure the packet's data is created */
594 data
= new uint8_t[request
.getSize()];
598 DPRINTFS(MinorMem
, (&port
), "Copying read data\n");
599 std::memcpy(packet
->getPtr
<uint8_t>(), data
, request
.getSize());
601 packet
->makeResponse();
604 /* Packets are all deallocated together in ~SplitLSQRequest */
608 LSQ::SplitDataRequest::sendNextFragmentToTranslation()
610 unsigned int fragment_index
= numTranslatedFragments
;
612 ThreadContext
*thread
= port
.cpu
.getContext(
615 DPRINTFS(MinorMem
, (&port
), "Submitting DTLB request for fragment: %d\n",
618 port
.numAccessesInDTLB
++;
619 numInTranslationFragments
++;
621 thread
->getDTBPtr()->translateTiming(
622 fragmentRequests
[fragment_index
], thread
, this, (isLoad
?
623 BaseTLB::Read
: BaseTLB::Write
));
627 LSQ::StoreBuffer::canInsert() const
629 /* @todo, support store amalgamation */
630 return slots
.size() < numSlots
;
634 LSQ::StoreBuffer::deleteRequest(LSQRequestPtr request
)
636 auto found
= std::find(slots
.begin(), slots
.end(), request
);
638 if (found
!= slots
.end()) {
639 DPRINTF(MinorMem
, "Deleting request: %s %s %s from StoreBuffer\n",
640 request
, *found
, *(request
->inst
));
648 LSQ::StoreBuffer::insert(LSQRequestPtr request
)
651 warn("%s: store buffer insertion without space to insert from"
652 " inst: %s\n", name(), *(request
->inst
));
655 DPRINTF(MinorMem
, "Pushing store: %s into store buffer\n", request
);
657 numUnissuedAccesses
++;
659 if (request
->state
!= LSQRequest::Complete
)
660 request
->setState(LSQRequest::StoreInStoreBuffer
);
662 slots
.push_back(request
);
664 /* Let's try and wake up the processor for the next cycle to step
665 * the store buffer */
666 lsq
.cpu
.wakeupOnEvent(Pipeline::ExecuteStageId
);
669 LSQ::AddrRangeCoverage
670 LSQ::StoreBuffer::canForwardDataToLoad(LSQRequestPtr request
,
671 unsigned int &found_slot
)
673 unsigned int slot_index
= slots
.size() - 1;
674 auto i
= slots
.rbegin();
675 AddrRangeCoverage ret
= NoAddrRangeCoverage
;
677 /* Traverse the store buffer in reverse order (most to least recent)
678 * and try to find a slot whose address range overlaps this request */
679 while (ret
== NoAddrRangeCoverage
&& i
!= slots
.rend()) {
680 LSQRequestPtr slot
= *i
;
683 slot
->inst
->id
.threadId
== request
->inst
->id
.threadId
) {
684 AddrRangeCoverage coverage
= slot
->containsAddrRangeOf(request
);
686 if (coverage
!= NoAddrRangeCoverage
) {
687 DPRINTF(MinorMem
, "Forwarding: slot: %d result: %s thisAddr:"
688 " 0x%x thisSize: %d slotAddr: 0x%x slotSize: %d\n",
689 slot_index
, coverage
,
690 request
->request
.getPaddr(), request
->request
.getSize(),
691 slot
->request
.getPaddr(), slot
->request
.getSize());
693 found_slot
= slot_index
;
705 /** Fill the given packet with appropriate date from slot slot_number */
707 LSQ::StoreBuffer::forwardStoreData(LSQRequestPtr load
,
708 unsigned int slot_number
)
710 assert(slot_number
< slots
.size());
711 assert(load
->packet
);
712 assert(load
->isLoad
);
714 LSQRequestPtr store
= slots
[slot_number
];
716 assert(store
->packet
);
717 assert(store
->containsAddrRangeOf(load
) == FullAddrRangeCoverage
);
719 Addr load_addr
= load
->request
.getPaddr();
720 Addr store_addr
= store
->request
.getPaddr();
721 Addr addr_offset
= load_addr
- store_addr
;
723 unsigned int load_size
= load
->request
.getSize();
725 DPRINTF(MinorMem
, "Forwarding %d bytes for addr: 0x%x from store buffer"
726 " slot: %d addr: 0x%x addressOffset: 0x%x\n",
727 load_size
, load_addr
, slot_number
,
728 store_addr
, addr_offset
);
730 void *load_packet_data
= load
->packet
->getPtr
<void>();
731 void *store_packet_data
= store
->packet
->getPtr
<uint8_t>() + addr_offset
;
733 std::memcpy(load_packet_data
, store_packet_data
, load_size
);
737 LSQ::StoreBuffer::countIssuedStore(LSQRequestPtr request
)
739 /* Barriers are accounted for as they are cleared from
740 * the queue, not after their transfers are complete */
741 if (!request
->isBarrier())
742 numUnissuedAccesses
--;
746 LSQ::StoreBuffer::step()
748 DPRINTF(MinorMem
, "StoreBuffer step numUnissuedAccesses: %d\n",
749 numUnissuedAccesses
);
751 if (numUnissuedAccesses
!= 0 && lsq
.state
== LSQ::MemoryRunning
) {
752 /* Clear all the leading barriers */
753 while (!slots
.empty() &&
754 slots
.front()->isComplete() && slots
.front()->isBarrier())
756 LSQRequestPtr barrier
= slots
.front();
758 DPRINTF(MinorMem
, "Clearing barrier for inst: %s\n",
761 numUnissuedAccesses
--;
762 lsq
.clearMemBarrier(barrier
->inst
);
768 auto i
= slots
.begin();
770 unsigned int issue_count
= 0;
772 /* Skip trying if the memory system is busy */
773 if (lsq
.state
== LSQ::MemoryNeedsRetry
)
776 /* Try to issue all stores in order starting from the head
777 * of the queue. Responses are allowed to be retired
780 issue_count
< storeLimitPerCycle
&&
781 lsq
.canSendToMemorySystem() &&
784 LSQRequestPtr request
= *i
;
786 DPRINTF(MinorMem
, "Considering request: %s, sentAllPackets: %d"
788 *(request
->inst
), request
->sentAllPackets(),
791 if (request
->isBarrier() && request
->isComplete()) {
792 /* Give up at barriers */
794 } else if (!(request
->state
== LSQRequest::StoreBufferIssuing
&&
795 request
->sentAllPackets()))
797 DPRINTF(MinorMem
, "Trying to send request: %s to memory"
798 " system\n", *(request
->inst
));
800 if (lsq
.tryToSend(request
)) {
801 countIssuedStore(request
);
804 /* Don't step on to the next store buffer entry if this
805 * one hasn't issued all its packets as the store
806 * buffer must still enforce ordering */
816 LSQ::completeMemBarrierInst(MinorDynInstPtr inst
,
820 /* Not already sent to the store buffer as a store request? */
821 if (!inst
->inStoreBuffer
) {
822 /* Insert an entry into the store buffer to tick off barriers
823 * until there are none in flight */
824 storeBuffer
.insert(new BarrierDataRequest(*this, inst
));
827 /* Clear the barrier anyway if it wasn't actually committed */
828 clearMemBarrier(inst
);
833 LSQ::StoreBuffer::minorTrace() const
835 unsigned int size
= slots
.size();
837 std::ostringstream os
;
840 LSQRequestPtr request
= slots
[i
];
842 request
->reportData(os
);
849 while (i
< numSlots
) {
857 MINORTRACE("addr=%s num_unissued_stores=%d\n", os
.str(),
858 numUnissuedAccesses
);
862 LSQ::tryToSendToTransfers(LSQRequestPtr request
)
864 if (state
== MemoryNeedsRetry
) {
865 DPRINTF(MinorMem
, "Request needs retry, not issuing to"
866 " memory until retry arrives\n");
870 if (request
->state
== LSQRequest::InTranslation
) {
871 DPRINTF(MinorMem
, "Request still in translation, not issuing to"
876 assert(request
->state
== LSQRequest::Translated
||
877 request
->state
== LSQRequest::RequestIssuing
||
878 request
->state
== LSQRequest::Failed
||
879 request
->state
== LSQRequest::Complete
);
881 if (requests
.empty() || requests
.front() != request
) {
882 DPRINTF(MinorMem
, "Request not at front of requests queue, can't"
883 " issue to memory\n");
887 if (transfers
.unreservedRemainingSpace() == 0) {
888 DPRINTF(MinorMem
, "No space to insert request into transfers"
893 if (request
->isComplete() || request
->state
== LSQRequest::Failed
) {
894 DPRINTF(MinorMem
, "Passing a %s transfer on to transfers"
895 " queue\n", (request
->isComplete() ? "completed" : "failed"));
896 request
->setState(LSQRequest::Complete
);
897 request
->setSkipped();
898 moveFromRequestsToTransfers(request
);
902 if (!execute
.instIsRightStream(request
->inst
)) {
903 /* Wrong stream, try to abort the transfer but only do so if
904 * there are no packets in flight */
905 if (request
->hasPacketsInMemSystem()) {
906 DPRINTF(MinorMem
, "Request's inst. is from the wrong stream,"
907 " waiting for responses before aborting request\n");
909 DPRINTF(MinorMem
, "Request's inst. is from the wrong stream,"
910 " aborting request\n");
911 request
->setState(LSQRequest::Complete
);
912 request
->setSkipped();
913 moveFromRequestsToTransfers(request
);
918 if (request
->fault
!= NoFault
) {
919 if (request
->inst
->staticInst
->isPrefetch()) {
920 DPRINTF(MinorMem
, "Not signalling fault for faulting prefetch\n");
922 DPRINTF(MinorMem
, "Moving faulting request into the transfers"
924 request
->setState(LSQRequest::Complete
);
925 request
->setSkipped();
926 moveFromRequestsToTransfers(request
);
930 bool is_load
= request
->isLoad
;
931 bool is_llsc
= request
->request
.isLLSC();
932 bool is_swap
= request
->request
.isSwap();
933 bool bufferable
= !(request
->request
.isStrictlyOrdered() ||
937 if (numStoresInTransfers
!= 0) {
938 DPRINTF(MinorMem
, "Load request with stores still in transfers"
939 " queue, stalling\n");
943 /* Store. Can it be sent to the store buffer? */
944 if (bufferable
&& !request
->request
.isMmappedIpr()) {
945 request
->setState(LSQRequest::StoreToStoreBuffer
);
946 moveFromRequestsToTransfers(request
);
947 DPRINTF(MinorMem
, "Moving store into transfers queue\n");
952 /* Check if this is the head instruction (and so must be executable as
953 * its stream sequence number was checked above) for loads which must
954 * not be speculatively issued and stores which must be issued here */
956 if (!execute
.instIsHeadInst(request
->inst
)) {
957 DPRINTF(MinorMem
, "Memory access not the head inst., can't be"
958 " sure it can be performed, not issuing\n");
962 unsigned int forwarding_slot
= 0;
964 if (storeBuffer
.canForwardDataToLoad(request
, forwarding_slot
) !=
967 DPRINTF(MinorMem
, "Memory access can receive forwarded data"
968 " from the store buffer, need to wait for store buffer to"
974 /* True: submit this packet to the transfers queue to be sent to the
976 * False: skip the memory and push a packet for this request onto
978 bool do_access
= true;
981 /* Check for match in the store buffer */
983 unsigned int forwarding_slot
= 0;
984 AddrRangeCoverage forwarding_result
=
985 storeBuffer
.canForwardDataToLoad(request
,
988 switch (forwarding_result
) {
989 case FullAddrRangeCoverage
:
990 /* Forward data from the store buffer into this request and
991 * repurpose this request's packet into a response packet */
992 storeBuffer
.forwardStoreData(request
, forwarding_slot
);
993 request
->packet
->makeResponse();
995 /* Just move between queues, no access */
998 case PartialAddrRangeCoverage
:
999 DPRINTF(MinorMem
, "Load partly satisfied by store buffer"
1000 " data. Must wait for the store to complete\n");
1003 case NoAddrRangeCoverage
:
1004 DPRINTF(MinorMem
, "No forwardable data from store buffer\n");
1005 /* Fall through to try access */
1010 if (!canSendToMemorySystem()) {
1011 DPRINTF(MinorMem
, "Can't send request to memory system yet\n");
1015 SimpleThread
&thread
= *cpu
.threads
[request
->inst
->id
.threadId
];
1017 TheISA::PCState old_pc
= thread
.pcState();
1018 ExecContext
context(cpu
, thread
, execute
, request
->inst
);
1020 /* Handle LLSC requests and tests */
1022 TheISA::handleLockedRead(&context
, &request
->request
);
1024 do_access
= TheISA::handleLockedWrite(&context
,
1025 &request
->request
, cacheBlockMask
);
1028 DPRINTF(MinorMem
, "Not perfoming a memory "
1029 "access for store conditional\n");
1032 thread
.pcState(old_pc
);
1035 /* See the do_access comment above */
1037 if (!canSendToMemorySystem()) {
1038 DPRINTF(MinorMem
, "Can't send request to memory system yet\n");
1042 /* Remember if this is an access which can't be idly
1043 * discarded by an interrupt */
1044 if (!bufferable
&& !request
->issuedToMemory
) {
1045 numAccessesIssuedToMemory
++;
1046 request
->issuedToMemory
= true;
1049 if (tryToSend(request
)) {
1050 moveFromRequestsToTransfers(request
);
1053 request
->setState(LSQRequest::Complete
);
1054 moveFromRequestsToTransfers(request
);
1059 LSQ::tryToSend(LSQRequestPtr request
)
1063 if (!canSendToMemorySystem()) {
1064 DPRINTF(MinorMem
, "Can't send request: %s yet, no space in memory\n",
1067 PacketPtr packet
= request
->getHeadPacket();
1069 DPRINTF(MinorMem
, "Trying to send request: %s addr: 0x%x\n",
1070 *(request
->inst
), packet
->req
->getVaddr());
1072 /* The sender state of the packet *must* be an LSQRequest
1073 * so the response can be correctly handled */
1074 assert(packet
->findNextSenderState
<LSQRequest
>());
1076 if (request
->request
.isMmappedIpr()) {
1077 ThreadContext
*thread
=
1078 cpu
.getContext(cpu
.contextToThread(
1079 request
->request
.contextId()));
1081 if (request
->isLoad
) {
1082 DPRINTF(MinorMem
, "IPR read inst: %s\n", *(request
->inst
));
1083 TheISA::handleIprRead(thread
, packet
);
1085 DPRINTF(MinorMem
, "IPR write inst: %s\n", *(request
->inst
));
1086 TheISA::handleIprWrite(thread
, packet
);
1089 request
->stepToNextPacket();
1090 ret
= request
->sentAllPackets();
1093 DPRINTF(MinorMem
, "IPR access has another packet: %s\n",
1098 request
->setState(LSQRequest::Complete
);
1100 request
->setState(LSQRequest::RequestIssuing
);
1101 } else if (dcachePort
.sendTimingReq(packet
)) {
1102 DPRINTF(MinorMem
, "Sent data memory request\n");
1104 numAccessesInMemorySystem
++;
1106 request
->stepToNextPacket();
1108 ret
= request
->sentAllPackets();
1110 switch (request
->state
) {
1111 case LSQRequest::Translated
:
1112 case LSQRequest::RequestIssuing
:
1113 /* Fully or partially issued a request in the transfers
1115 request
->setState(LSQRequest::RequestIssuing
);
1117 case LSQRequest::StoreInStoreBuffer
:
1118 case LSQRequest::StoreBufferIssuing
:
1119 /* Fully or partially issued a request in the store
1121 request
->setState(LSQRequest::StoreBufferIssuing
);
1128 state
= MemoryRunning
;
1131 "Sending data memory request - needs retry\n");
1133 /* Needs to be resent, wait for that */
1134 state
= MemoryNeedsRetry
;
1135 retryRequest
= request
;
1137 switch (request
->state
) {
1138 case LSQRequest::Translated
:
1139 case LSQRequest::RequestIssuing
:
1140 request
->setState(LSQRequest::RequestNeedsRetry
);
1142 case LSQRequest::StoreInStoreBuffer
:
1143 case LSQRequest::StoreBufferIssuing
:
1144 request
->setState(LSQRequest::StoreBufferNeedsRetry
);
1154 threadSnoop(request
);
1160 LSQ::moveFromRequestsToTransfers(LSQRequestPtr request
)
1162 assert(!requests
.empty() && requests
.front() == request
);
1163 assert(transfers
.unreservedRemainingSpace() != 0);
1165 /* Need to count the number of stores in the transfers
1166 * queue so that loads know when their store buffer forwarding
1167 * results will be correct (only when all those stores
1168 * have reached the store buffer) */
1169 if (!request
->isLoad
)
1170 numStoresInTransfers
++;
1173 transfers
.push(request
);
1177 LSQ::canSendToMemorySystem()
1179 return state
== MemoryRunning
&&
1180 numAccessesInMemorySystem
< inMemorySystemLimit
;
1184 LSQ::recvTimingResp(PacketPtr response
)
1186 LSQRequestPtr request
=
1187 safe_cast
<LSQRequestPtr
>(response
->popSenderState());
1189 DPRINTF(MinorMem
, "Received response packet inst: %s"
1190 " addr: 0x%x cmd: %s\n",
1191 *(request
->inst
), response
->getAddr(),
1192 response
->cmd
.toString());
1194 numAccessesInMemorySystem
--;
1196 if (response
->isError()) {
1197 DPRINTF(MinorMem
, "Received error response packet: %s\n",
1201 switch (request
->state
) {
1202 case LSQRequest::RequestIssuing
:
1203 case LSQRequest::RequestNeedsRetry
:
1204 /* Response to a request from the transfers queue */
1205 request
->retireResponse(response
);
1207 DPRINTF(MinorMem
, "Has outstanding packets?: %d %d\n",
1208 request
->hasPacketsInMemSystem(), request
->isComplete());
1211 case LSQRequest::StoreBufferIssuing
:
1212 case LSQRequest::StoreBufferNeedsRetry
:
1213 /* Response to a request from the store buffer */
1214 request
->retireResponse(response
);
1216 /* Remove completed requests unless they are barriers (which will
1217 * need to be removed in order */
1218 if (request
->isComplete()) {
1219 if (!request
->isBarrier()) {
1220 storeBuffer
.deleteRequest(request
);
1222 DPRINTF(MinorMem
, "Completed transfer for barrier: %s"
1223 " leaving the request as it is also a barrier\n",
1229 /* Shouldn't be allowed to receive a response from another
1235 /* We go to idle even if there are more things in the requests queue
1236 * as it's the job of step to actually step us on to the next
1239 /* Let's try and wake up the processor for the next cycle */
1240 cpu
.wakeupOnEvent(Pipeline::ExecuteStageId
);
1249 DPRINTF(MinorMem
, "Received retry request\n");
1251 assert(state
== MemoryNeedsRetry
);
1253 switch (retryRequest
->state
) {
1254 case LSQRequest::RequestNeedsRetry
:
1255 /* Retry in the requests queue */
1256 retryRequest
->setState(LSQRequest::Translated
);
1258 case LSQRequest::StoreBufferNeedsRetry
:
1259 /* Retry in the store buffer */
1260 retryRequest
->setState(LSQRequest::StoreInStoreBuffer
);
1266 /* Set state back to MemoryRunning so that the following
1267 * tryToSend can actually send. Note that this won't
1268 * allow another transfer in as tryToSend should
1269 * issue a memory request and either succeed for this
1270 * request or return the LSQ back to MemoryNeedsRetry */
1271 state
= MemoryRunning
;
1273 /* Try to resend the request */
1274 if (tryToSend(retryRequest
)) {
1275 /* Successfully sent, need to move the request */
1276 switch (retryRequest
->state
) {
1277 case LSQRequest::RequestIssuing
:
1278 /* In the requests queue */
1279 moveFromRequestsToTransfers(retryRequest
);
1281 case LSQRequest::StoreBufferIssuing
:
1282 /* In the store buffer */
1283 storeBuffer
.countIssuedStore(retryRequest
);
1290 retryRequest
= NULL
;
1294 LSQ::LSQ(std::string name_
, std::string dcache_port_name_
,
1295 MinorCPU
&cpu_
, Execute
&execute_
,
1296 unsigned int in_memory_system_limit
, unsigned int line_width
,
1297 unsigned int requests_queue_size
, unsigned int transfers_queue_size
,
1298 unsigned int store_buffer_size
,
1299 unsigned int store_buffer_cycle_store_limit
) :
1303 dcachePort(dcache_port_name_
, *this, cpu_
),
1304 lastMemBarrier(cpu
.numThreads
, 0),
1305 state(MemoryRunning
),
1306 inMemorySystemLimit(in_memory_system_limit
),
1307 lineWidth((line_width
== 0 ? cpu
.cacheLineSize() : line_width
)),
1308 requests(name_
+ ".requests", "addr", requests_queue_size
),
1309 transfers(name_
+ ".transfers", "addr", transfers_queue_size
),
1310 storeBuffer(name_
+ ".storeBuffer",
1311 *this, store_buffer_size
, store_buffer_cycle_store_limit
),
1312 numAccessesInMemorySystem(0),
1313 numAccessesInDTLB(0),
1314 numStoresInTransfers(0),
1315 numAccessesIssuedToMemory(0),
1317 cacheBlockMask(~(cpu_
.cacheLineSize() - 1))
1319 if (in_memory_system_limit
< 1) {
1320 fatal("%s: executeMaxAccessesInMemory must be >= 1 (%d)\n", name_
,
1321 in_memory_system_limit
);
1324 if (store_buffer_cycle_store_limit
< 1) {
1325 fatal("%s: executeLSQMaxStoreBufferStoresPerCycle must be"
1326 " >= 1 (%d)\n", name_
, store_buffer_cycle_store_limit
);
1329 if (requests_queue_size
< 1) {
1330 fatal("%s: executeLSQRequestsQueueSize must be"
1331 " >= 1 (%d)\n", name_
, requests_queue_size
);
1334 if (transfers_queue_size
< 1) {
1335 fatal("%s: executeLSQTransfersQueueSize must be"
1336 " >= 1 (%d)\n", name_
, transfers_queue_size
);
1339 if (store_buffer_size
< 1) {
1340 fatal("%s: executeLSQStoreBufferSize must be"
1341 " >= 1 (%d)\n", name_
, store_buffer_size
);
1344 if ((lineWidth
& (lineWidth
- 1)) != 0) {
1345 fatal("%s: lineWidth: %d must be a power of 2\n", name(), lineWidth
);
1352 LSQ::LSQRequest::~LSQRequest()
1361 * Step the memory access mechanism on to its next state. In reality, most
1362 * of the stepping is done by the callbacks on the LSQ but this
1363 * function is responsible for issuing memory requests lodged in the
1369 /* Try to move address-translated requests between queues and issue
1371 if (!requests
.empty())
1372 tryToSendToTransfers(requests
.front());
1378 LSQ::findResponse(MinorDynInstPtr inst
)
1380 LSQ::LSQRequestPtr ret
= NULL
;
1382 if (!transfers
.empty()) {
1383 LSQRequestPtr request
= transfers
.front();
1385 /* Same instruction and complete access or a store that's
1386 * capable of being moved to the store buffer */
1387 if (request
->inst
->id
== inst
->id
) {
1388 bool complete
= request
->isComplete();
1389 bool can_store
= storeBuffer
.canInsert();
1390 bool to_store_buffer
= request
->state
==
1391 LSQRequest::StoreToStoreBuffer
;
1393 if ((complete
&& !(request
->isBarrier() && !can_store
)) ||
1394 (to_store_buffer
&& can_store
))
1402 DPRINTF(MinorMem
, "Found matching memory response for inst: %s\n",
1405 DPRINTF(MinorMem
, "No matching memory response for inst: %s\n",
1413 LSQ::popResponse(LSQ::LSQRequestPtr response
)
1415 assert(!transfers
.empty() && transfers
.front() == response
);
1419 if (!response
->isLoad
)
1420 numStoresInTransfers
--;
1422 if (response
->issuedToMemory
)
1423 numAccessesIssuedToMemory
--;
1425 if (response
->state
!= LSQRequest::StoreInStoreBuffer
) {
1426 DPRINTF(MinorMem
, "Deleting %s request: %s\n",
1427 (response
->isLoad
? "load" : "store"),
1435 LSQ::sendStoreToStoreBuffer(LSQRequestPtr request
)
1437 assert(request
->state
== LSQRequest::StoreToStoreBuffer
);
1439 DPRINTF(MinorMem
, "Sending store: %s to store buffer\n",
1442 request
->inst
->inStoreBuffer
= true;
1444 storeBuffer
.insert(request
);
1450 return requests
.empty() && transfers
.empty() &&
1451 storeBuffer
.isDrained();
1459 if (canSendToMemorySystem()) {
1460 bool have_translated_requests
= !requests
.empty() &&
1461 requests
.front()->state
!= LSQRequest::InTranslation
&&
1462 transfers
.unreservedRemainingSpace() != 0;
1464 ret
= have_translated_requests
||
1465 storeBuffer
.numUnissuedStores() != 0;
1469 DPRINTF(Activity
, "Need to tick\n");
1475 LSQ::pushRequest(MinorDynInstPtr inst
, bool isLoad
, uint8_t *data
,
1476 unsigned int size
, Addr addr
, Request::Flags flags
,
1479 bool needs_burst
= transferNeedsBurst(addr
, size
, lineWidth
);
1480 LSQRequestPtr request
;
1482 /* Copy given data into the request. The request will pass this to the
1483 * packet and then it will own the data */
1484 uint8_t *request_data
= NULL
;
1486 DPRINTF(MinorMem
, "Pushing request (%s) addr: 0x%x size: %d flags:"
1487 " 0x%x%s lineWidth : 0x%x\n",
1488 (isLoad
? "load" : "store"), addr
, size
, flags
,
1489 (needs_burst
? " (needs burst)" : ""), lineWidth
);
1492 /* request_data becomes the property of a ...DataRequest (see below)
1493 * and destroyed by its destructor */
1494 request_data
= new uint8_t[size
];
1495 if (flags
& Request::CACHE_BLOCK_ZERO
) {
1496 /* For cache zeroing, just use zeroed data */
1497 std::memset(request_data
, 0, size
);
1499 std::memcpy(request_data
, data
, size
);
1504 request
= new SplitDataRequest(
1505 *this, inst
, isLoad
, request_data
, res
);
1507 request
= new SingleDataRequest(
1508 *this, inst
, isLoad
, request_data
, res
);
1511 if (inst
->traceData
)
1512 inst
->traceData
->setMem(addr
, size
, flags
);
1514 int cid
= cpu
.threads
[inst
->id
.threadId
]->getTC()->contextId();
1515 request
->request
.setContext(cid
);
1516 request
->request
.setVirt(0 /* asid */,
1517 addr
, size
, flags
, cpu
.dataMasterId(),
1518 /* I've no idea why we need the PC, but give it */
1519 inst
->pc
.instAddr());
1521 requests
.push(request
);
1522 request
->startAddrTranslation();
1526 LSQ::pushFailedRequest(MinorDynInstPtr inst
)
1528 LSQRequestPtr request
= new FailedDataRequest(*this, inst
);
1529 requests
.push(request
);
1533 LSQ::minorTrace() const
1535 MINORTRACE("state=%s in_tlb_mem=%d/%d stores_in_transfers=%d"
1536 " lastMemBarrier=%d\n",
1537 state
, numAccessesInDTLB
, numAccessesInMemorySystem
,
1538 numStoresInTransfers
, lastMemBarrier
[0]);
1539 requests
.minorTrace();
1540 transfers
.minorTrace();
1541 storeBuffer
.minorTrace();
1544 LSQ::StoreBuffer::StoreBuffer(std::string name_
, LSQ
&lsq_
,
1545 unsigned int store_buffer_size
,
1546 unsigned int store_limit_per_cycle
) :
1547 Named(name_
), lsq(lsq_
),
1548 numSlots(store_buffer_size
),
1549 storeLimitPerCycle(store_limit_per_cycle
),
1551 numUnissuedAccesses(0)
1556 makePacketForRequest(Request
&request
, bool isLoad
,
1557 Packet::SenderState
*sender_state
, PacketDataPtr data
)
1559 PacketPtr ret
= isLoad
? Packet::createRead(&request
)
1560 : Packet::createWrite(&request
);
1563 ret
->pushSenderState(sender_state
);
1568 ret
->dataDynamic(data
);
1574 LSQ::issuedMemBarrierInst(MinorDynInstPtr inst
)
1576 assert(inst
->isInst() && inst
->staticInst
->isMemBarrier());
1577 assert(inst
->id
.execSeqNum
> lastMemBarrier
[inst
->id
.threadId
]);
1579 /* Remember the barrier. We only have a notion of one
1580 * barrier so this may result in some mem refs being
1581 * delayed if they are between barriers */
1582 lastMemBarrier
[inst
->id
.threadId
] = inst
->id
.execSeqNum
;
1586 LSQ::LSQRequest::makePacket()
1588 /* Make the function idempotent */
1592 // if the translation faulted, do not create a packet
1593 if (fault
!= NoFault
) {
1594 assert(packet
== NULL
);
1598 packet
= makePacketForRequest(request
, isLoad
, this, data
);
1599 /* Null the ret data so we know not to deallocate it when the
1600 * ret is destroyed. The data now belongs to the ret and
1601 * the ret is responsible for its destruction */
1606 operator <<(std::ostream
&os
, LSQ::MemoryState state
)
1609 case LSQ::MemoryRunning
:
1610 os
<< "MemoryRunning";
1612 case LSQ::MemoryNeedsRetry
:
1613 os
<< "MemoryNeedsRetry";
1616 os
<< "MemoryState-" << static_cast<int>(state
);
1623 LSQ::recvTimingSnoopReq(PacketPtr pkt
)
1625 /* LLSC operations in Minor can't be speculative and are executed from
1626 * the head of the requests queue. We shouldn't need to do more than
1627 * this action on snoops. */
1628 for (ThreadID tid
= 0; tid
< cpu
.numThreads
; tid
++) {
1629 if (cpu
.getCpuAddrMonitor(tid
)->doMonitor(pkt
)) {
1634 if (pkt
->isInvalidate() || pkt
->isWrite()) {
1635 for (ThreadID tid
= 0; tid
< cpu
.numThreads
; tid
++) {
1636 TheISA::handleLockedSnoop(cpu
.getContext(tid
), pkt
,
1643 LSQ::threadSnoop(LSQRequestPtr request
)
1645 /* LLSC operations in Minor can't be speculative and are executed from
1646 * the head of the requests queue. We shouldn't need to do more than
1647 * this action on snoops. */
1648 ThreadID req_tid
= request
->inst
->id
.threadId
;
1649 PacketPtr pkt
= request
->packet
;
1651 for (ThreadID tid
= 0; tid
< cpu
.numThreads
; tid
++) {
1652 if (tid
!= req_tid
) {
1653 if (cpu
.getCpuAddrMonitor(tid
)->doMonitor(pkt
)) {
1657 if (pkt
->isInvalidate() || pkt
->isWrite()) {
1658 TheISA::handleLockedSnoop(cpu
.getContext(tid
), pkt
,