50#include "debug/Activity.hh"
51#include "debug/MinorMem.hh"
70 issuedToMemory(false),
71 isTranslationDelayed(false),
74 request = std::make_shared<Request>();
80 SimpleThread &thread = *port.cpu.threads[inst->id.threadId];
81 std::unique_ptr<PCStateBase> old_pc(thread.
pcState().
clone());
82 ExecContext context(port.cpu, thread, port.execute, inst);
83 [[maybe_unused]]
Fault fault = inst->translationFault;
86 inst->translationFault = inst->staticInst->initiateAcc(&context,
nullptr);
87 if (inst->translationFault ==
NoFault) {
89 "Translation fault suppressed for inst:%s\n", *inst);
91 assert(inst->translationFault == fault);
99 DPRINTFS(MinorMem, (&port),
"Complete disabled mem access for inst:%s\n",
102 SimpleThread &thread = *port.cpu.threads[inst->id.threadId];
103 std::unique_ptr<PCStateBase> old_pc(thread.
pcState().
clone());
105 ExecContext context(port.cpu, thread, port.execute, inst);
108 inst->staticInst->completeAcc(
nullptr, &context, inst->traceData);
116 port.cpu.threads[inst->id.threadId]->setMemAccPredicate(
false);
117 DPRINTFS(MinorMem, (&port),
"Disable mem access for inst:%s\n", *inst);
122 Addr req1_addr,
unsigned int req1_size,
123 Addr req2_addr,
unsigned int req2_size)
127 Addr req2_end_addr = req2_addr + req2_size;
128 Addr req1_end_addr = req1_addr + req1_size;
132 if (req1_addr >= req2_end_addr || req1_end_addr <= req2_addr)
134 else if (req1_addr <= req2_addr && req1_end_addr >= req2_end_addr)
146 request->getPaddr(), request->getSize(),
147 other_request->
request->getPaddr(), other_request->
request->getSize());
160 return inst->isInst() && inst->staticInst->isFullMemBarrier();
166 return state == StoreToStoreBuffer;
172 DPRINTFS(MinorMem, (&port),
"Setting state from %d to %d for request:"
173 " %s\n",
state, new_state, *inst);
188 os << (isLoad ?
'R' :
'W') <<
';';
189 inst->reportData(
os);
198 os <<
"PartialAddrRangeCoverage";
201 os <<
"FullAddrRangeCoverage";
204 os <<
"NoAddrRangeCoverage";
207 os <<
"AddrRangeCoverage-" <<
static_cast<int>(coverage);
221 os <<
"InTranslation";
230 os <<
"RequestIssuing";
233 os <<
"StoreToStoreBuffer";
236 os <<
"StoreInStoreBuffer";
239 os <<
"StoreBufferIssuing";
242 os <<
"RequestNeedsRetry";
245 os <<
"StoreBufferNeedsRetry";
251 os <<
"LSQRequestState-" <<
static_cast<int>(
state);
260 bool is_last_barrier =
263 DPRINTF(MinorMem,
"Moving %s barrier out of store buffer inst: %s\n",
264 (is_last_barrier ?
"last" :
"a"), *inst);
274 port.numAccessesInDTLB--;
276 DPRINTFS(MinorMem, (&port),
"Received translation response for"
277 " request: %s delayed:%d %s\n", *inst, isTranslationDelayed,
278 fault_ !=
NoFault ? fault_->name() :
"");
281 inst->translationFault = fault_;
282 if (isTranslationDelayed) {
283 tryToSuppressFault();
284 if (inst->translationFault ==
NoFault) {
285 completeDisabledMemAccess();
289 setState(Translated);
291 setState(Translated);
294 port.tryToSendToTransfers(
this);
306 const auto &byte_enable = request->getByteEnable();
308 port.numAccessesInDTLB++;
312 DPRINTFS(MinorMem, (&port),
"Submitting DTLB request\n");
327 DPRINTFS(MinorMem, (&port),
"Retiring packet\n");
329 packetInFlight =
false;
337 port.numAccessesInDTLB--;
339 [[maybe_unused]]
unsigned int expected_fragment_index =
340 numTranslatedFragments;
342 numInTranslationFragments--;
343 numTranslatedFragments++;
345 DPRINTFS(MinorMem, (&port),
"Received translation response for fragment"
346 " %d of request: %s delayed:%d %s\n", expected_fragment_index,
347 *inst, isTranslationDelayed,
348 fault_ !=
NoFault ? fault_->name() :
"");
350 assert(request_ == fragmentRequests[expected_fragment_index]);
358 inst->translationFault = fault_;
360 DPRINTFS(MinorMem, (&port),
"Faulting translation for fragment:"
361 " %d of request: %s\n",
362 expected_fragment_index, *inst);
364 if (expected_fragment_index > 0 || isTranslationDelayed)
365 tryToSuppressFault();
366 if (expected_fragment_index == 0) {
367 if (isTranslationDelayed && inst->translationFault ==
NoFault) {
368 completeDisabledMemAccess();
371 setState(Translated);
373 }
else if (inst->translationFault ==
NoFault) {
374 setState(Translated);
375 numTranslatedFragments--;
376 makeFragmentPackets();
378 setState(Translated);
380 port.tryToSendToTransfers(
this);
381 }
else if (numTranslatedFragments == numFragments) {
382 makeFragmentPackets();
383 setState(Translated);
384 port.tryToSendToTransfers(
this);
387 assert(!translationEvent.scheduled());
388 port.cpu.schedule(translationEvent,
curTick());
394 LSQRequest(port_, inst_, isLoad_, data_, res_),
398 numInTranslationFragments(0),
399 numTranslatedFragments(0),
400 numIssuedFragments(0),
401 numRetiredFragments(0),
411 for (
auto i = fragmentPackets.begin();
412 i != fragmentPackets.end();
i++)
421 Addr base_addr = request->getVaddr();
422 unsigned int whole_size = request->getSize();
423 unsigned int line_width = port.lineWidth;
425 unsigned int fragment_size;
442 unsigned int first_fragment_offset =
444 unsigned int last_fragment_size =
446 unsigned int first_fragment_size =
447 line_width - first_fragment_offset;
449 unsigned int middle_fragments_total_size =
450 whole_size - (first_fragment_size + last_fragment_size);
454 unsigned int middle_fragment_count =
455 middle_fragments_total_size / line_width;
457 numFragments = 1 + middle_fragment_count +
458 (last_fragment_size == 0 ? 0 : 1);
460 DPRINTFS(MinorMem, (&port),
"Dividing transfer into %d fragmentRequests."
461 " First fragment size: %d Last fragment size: %d\n",
462 numFragments, first_fragment_size,
463 (last_fragment_size == 0 ? line_width : last_fragment_size));
465 assert(((middle_fragment_count * line_width) +
466 first_fragment_size + last_fragment_size) == whole_size);
468 fragment_addr = base_addr;
469 fragment_size = first_fragment_size;
472 Addr end_addr = base_addr + whole_size;
474 auto& byte_enable = request->getByteEnable();
475 unsigned int num_disabled_fragments = 0;
477 for (
unsigned int fragment_index = 0; fragment_index < numFragments;
480 [[maybe_unused]]
bool is_last_fragment =
false;
482 if (fragment_addr == base_addr) {
484 fragment_size = first_fragment_size;
486 if ((fragment_addr + line_width) > end_addr) {
488 fragment_size = end_addr - fragment_addr;
489 is_last_fragment =
true;
492 fragment_size = line_width;
496 RequestPtr fragment = std::make_shared<Request>();
497 bool disabled_fragment =
false;
499 fragment->setContext(request->contextId());
501 auto it_start = byte_enable.begin() +
502 (fragment_addr - base_addr);
503 auto it_end = byte_enable.begin() +
504 (fragment_addr - base_addr) + fragment_size;
507 fragment_addr, fragment_size, request->getFlags(),
508 request->requestorId(),
512 disabled_fragment =
true;
515 if (!disabled_fragment) {
516 DPRINTFS(MinorMem, (&port),
"Generating fragment addr: 0x%x"
517 " size: %d (whole request addr: 0x%x size: %d) %s\n",
518 fragment_addr, fragment_size, base_addr, whole_size,
519 (is_last_fragment ?
"last fragment" :
""));
521 fragmentRequests.push_back(fragment);
523 num_disabled_fragments++;
526 fragment_addr += fragment_size;
528 assert(numFragments >= num_disabled_fragments);
529 numFragments -= num_disabled_fragments;
535 assert(numTranslatedFragments > 0);
536 Addr base_addr = request->getVaddr();
538 DPRINTFS(MinorMem, (&port),
"Making packets for request: %s\n", *inst);
540 for (
unsigned int fragment_index = 0;
541 fragment_index < numTranslatedFragments;
544 RequestPtr fragment = fragmentRequests[fragment_index];
546 DPRINTFS(MinorMem, (&port),
"Making packet %d for request: %s"
548 fragment_index, *inst,
549 (fragment->hasPaddr() ?
"has paddr" :
"no paddr"),
550 (fragment->hasPaddr() ? fragment->getPaddr() : 0));
552 Addr fragment_addr = fragment->getVaddr();
553 unsigned int fragment_size = fragment->getSize();
555 uint8_t *request_data = NULL;
560 request_data =
new uint8_t[fragment_size];
561 std::memcpy(request_data,
data + (fragment_addr - base_addr),
565 assert(fragment->hasPaddr());
570 fragmentPackets.push_back(fragment_packet);
572 request->setFlags(fragment->getFlags());
578 request->setPaddr(fragmentRequests[0]->getPaddr());
585 makeFragmentRequests();
587 if (numFragments > 0) {
589 numInTranslationFragments = 0;
590 numTranslatedFragments = 0;
600 sendNextFragmentToTranslation();
610 assert(numIssuedFragments < numTranslatedFragments);
612 return fragmentPackets[numIssuedFragments];
618 assert(numIssuedFragments < numTranslatedFragments);
620 numIssuedFragments++;
626 assert(inst->translationFault ==
NoFault);
627 assert(numRetiredFragments < numTranslatedFragments);
629 DPRINTFS(MinorMem, (&port),
"Retiring fragment addr: 0x%x size: %d"
630 " offset: 0x%x (retired fragment num: %d)\n",
631 response->
req->getVaddr(), response->
req->getSize(),
632 request->getVaddr() - response->
req->getVaddr(),
633 numRetiredFragments);
635 numRetiredFragments++;
640 DPRINTFS(MinorMem, (&port),
"Skipping this fragment\n");
641 }
else if (response->
isError()) {
643 DPRINTFS(MinorMem, (&port),
"Fragment has an error, skipping\n");
645 packet->copyError(response);
652 data =
new uint8_t[request->getSize()];
658 data + (response->
req->getVaddr() - request->getVaddr()),
660 response->
req->getSize());
665 if (skipped && !hasPacketsInMemSystem()) {
666 DPRINTFS(MinorMem, (&port),
"Completed skipped burst\n");
668 if (packet->needsResponse())
669 packet->makeResponse();
672 if (numRetiredFragments == numTranslatedFragments)
675 if (!skipped && isComplete()) {
676 DPRINTFS(MinorMem, (&port),
"Completed burst %d\n", packet != NULL);
678 DPRINTFS(MinorMem, (&port),
"Retired packet isRead: %d isWrite: %d"
679 " needsResponse: %d packetSize: %s requestSize: %s responseSize:"
680 " %s\n", packet->isRead(), packet->isWrite(),
681 packet->needsResponse(), packet->getSize(), request->getSize(),
687 data =
new uint8_t[request->getSize()];
691 DPRINTFS(MinorMem, (&port),
"Copying read data\n");
692 std::memcpy(packet->getPtr<uint8_t>(),
data, request->getSize());
694 packet->makeResponse();
703 unsigned int fragment_index = numTranslatedFragments;
708 DPRINTFS(MinorMem, (&port),
"Submitting DTLB request for fragment: %d\n",
711 port.numAccessesInDTLB++;
712 numInTranslationFragments++;
715 fragmentRequests[fragment_index], thread,
this, (isLoad ?
723 return slots.size() < numSlots;
729 auto found = std::find(slots.begin(), slots.end(), request);
731 if (found != slots.end()) {
732 DPRINTF(MinorMem,
"Deleting request: %s %s %s from StoreBuffer\n",
733 request, *found, *(request->
inst));
744 warn(
"%s: store buffer insertion without space to insert from"
745 " inst: %s\n",
name(), *(request->
inst));
748 DPRINTF(MinorMem,
"Pushing store: %s into store buffer\n", request);
750 numUnissuedAccesses++;
755 slots.push_back(request);
764 unsigned int &found_slot)
766 unsigned int slot_index = slots.size() - 1;
767 auto i = slots.rbegin();
779 slot->
inst->id.threadId == request->
inst->id.threadId &&
780 !slot->
packet->
req->isCacheMaintenance()) {
784 DPRINTF(MinorMem,
"Forwarding: slot: %d result: %s thisAddr:"
785 " 0x%x thisSize: %d slotAddr: 0x%x slotSize: %d\n",
786 slot_index, coverage,
790 found_slot = slot_index;
805 unsigned int slot_number)
807 assert(slot_number < slots.size());
818 Addr addr_offset = load_addr - store_addr;
820 unsigned int load_size = load->
request->getSize();
822 DPRINTF(MinorMem,
"Forwarding %d bytes for addr: 0x%x from store buffer"
823 " slot: %d addr: 0x%x addressOffset: 0x%x\n",
824 load_size, load_addr, slot_number,
825 store_addr, addr_offset);
828 void *store_packet_data = store->
packet->
getPtr<uint8_t>() + addr_offset;
830 std::memcpy(load_packet_data, store_packet_data, load_size);
839 numUnissuedAccesses--;
845 DPRINTF(MinorMem,
"StoreBuffer step numUnissuedAccesses: %d\n",
846 numUnissuedAccesses);
850 while (!slots.empty() &&
851 slots.front()->isComplete() && slots.front()->isBarrier())
855 DPRINTF(MinorMem,
"Clearing barrier for inst: %s\n",
858 numUnissuedAccesses--;
859 lsq.clearMemBarrier(barrier->
inst);
865 auto i = slots.begin();
867 unsigned int issue_count = 0;
877 issue_count < storeLimitPerCycle &&
878 lsq.canSendToMemorySystem() &&
883 DPRINTF(MinorMem,
"Considering request: %s, sentAllPackets: %d"
894 DPRINTF(MinorMem,
"Trying to send request: %s to memory"
895 " system\n", *(request->
inst));
897 if (lsq.tryToSend(request)) {
898 countIssuedStore(request);
918 if (!inst->inStoreBuffer) {
932 unsigned int size = slots.size();
934 std::ostringstream
os;
946 while (
i < numSlots) {
955 numUnissuedAccesses);
962 DPRINTF(MinorMem,
"Request needs retry, not issuing to"
963 " memory until retry arrives\n");
968 DPRINTF(MinorMem,
"Request still in translation, not issuing to"
979 DPRINTF(MinorMem,
"Request not at front of requests queue, can't"
980 " issue to memory\n");
985 DPRINTF(MinorMem,
"No space to insert request into transfers"
991 DPRINTF(MinorMem,
"Passing a %s transfer on to transfers"
992 " queue\n", (request->
isComplete() ?
"completed" :
"failed"));
1003 DPRINTF(MinorMem,
"Request's inst. is from the wrong stream,"
1004 " waiting for responses before aborting request\n");
1006 DPRINTF(MinorMem,
"Request's inst. is from the wrong stream,"
1007 " aborting request\n");
1016 if (request->
inst->staticInst->isPrefetch()) {
1017 DPRINTF(MinorMem,
"Not signalling fault for faulting prefetch\n");
1019 DPRINTF(MinorMem,
"Moving faulting request into the transfers"
1027 bool is_load = request->
isLoad;
1028 bool is_llsc = request->
request->isLLSC();
1029 bool is_release = request->
request->isRelease();
1030 bool is_swap = request->
request->isSwap();
1031 bool is_atomic = request->
request->isAtomic();
1032 bool bufferable = !(request->
request->isStrictlyOrdered() ||
1033 is_llsc || is_swap || is_atomic || is_release);
1037 DPRINTF(MinorMem,
"Load request with stores still in transfers"
1038 " queue, stalling\n");
1043 if (bufferable && !request->
request->isLocalAccess()) {
1046 DPRINTF(MinorMem,
"Moving store into transfers queue\n");
1053 if (((!is_load && is_llsc) || is_release) &&
1055 DPRINTF(MinorMem,
"Memory access needs to wait for store buffer"
1065 DPRINTF(MinorMem,
"Memory access not the head inst., can't be"
1066 " sure it can be performed, not issuing\n");
1070 unsigned int forwarding_slot = 0;
1082 DPRINTF(MinorMem,
"Memory access can receive forwarded data"
1083 " from the store buffer, but need to wait for store buffer"
1093 bool do_access =
true;
1098 unsigned int forwarding_slot = 0;
1103 switch (forwarding_result) {
1114 DPRINTF(MinorMem,
"Load partly satisfied by store buffer"
1115 " data. Must wait for the store to complete\n");
1119 DPRINTF(MinorMem,
"No forwardable data from store buffer\n");
1126 DPRINTF(MinorMem,
"Can't send request to memory system yet\n");
1132 std::unique_ptr<PCStateBase> old_pc(thread.
pcState().
clone());
1143 DPRINTF(MinorMem,
"Not perfoming a memory "
1144 "access for store conditional\n");
1153 DPRINTF(MinorMem,
"Can't send request to memory system yet\n");
1179 DPRINTF(MinorMem,
"Can't send request: %s yet, no space in memory\n",
1184 DPRINTF(MinorMem,
"Trying to send request: %s addr: 0x%x\n",
1185 *(request->
inst), packet->
req->getVaddr());
1191 if (request->
request->isLocalAccess()) {
1194 request->
request->contextId()));
1197 DPRINTF(MinorMem,
"IPR read inst: %s\n", *(request->
inst));
1199 DPRINTF(MinorMem,
"IPR write inst: %s\n", *(request->
inst));
1201 request->
request->localAccessor(thread, packet);
1207 DPRINTF(MinorMem,
"IPR access has another packet: %s\n",
1216 DPRINTF(MinorMem,
"Sent data memory request\n");
1224 switch (request->
state) {
1238 panic(
"Unrecognized LSQ request state %d.", request->
state);
1244 "Sending data memory request - needs retry\n");
1250 switch (request->
state) {
1260 panic(
"Unrecognized LSQ request state %d.", request->
state);
1301 DPRINTF(MinorMem,
"Received response packet inst: %s"
1302 " addr: 0x%x cmd: %s\n",
1309 DPRINTF(MinorMem,
"Received error response packet: %s\n",
1313 switch (request->
state) {
1319 DPRINTF(MinorMem,
"Has outstanding packets?: %d %d\n",
1334 DPRINTF(MinorMem,
"Completed transfer for barrier: %s"
1335 " leaving the request as it is also a barrier\n",
1341 panic(
"Shouldn't be allowed to receive a response from another state");
1358 DPRINTF(MinorMem,
"Received retry request\n");
1402LSQ::LSQ(std::string name_, std::string dcache_port_name_,
1404 unsigned int in_memory_system_limit,
unsigned int line_width,
1405 unsigned int requests_queue_size,
unsigned int transfers_queue_size,
1406 unsigned int store_buffer_size,
1407 unsigned int store_buffer_cycle_store_limit) :
1415 lineWidth((line_width == 0 ?
cpu.cacheLineSize() : line_width)),
1416 requests(name_ +
".requests",
"addr", requests_queue_size),
1417 transfers(name_ +
".transfers",
"addr", transfers_queue_size),
1419 *this, store_buffer_size, store_buffer_cycle_store_limit),
1427 if (in_memory_system_limit < 1) {
1428 fatal(
"%s: executeMaxAccessesInMemory must be >= 1 (%d)\n", name_,
1429 in_memory_system_limit);
1432 if (store_buffer_cycle_store_limit < 1) {
1433 fatal(
"%s: executeLSQMaxStoreBufferStoresPerCycle must be"
1434 " >= 1 (%d)\n", name_, store_buffer_cycle_store_limit);
1437 if (requests_queue_size < 1) {
1438 fatal(
"%s: executeLSQRequestsQueueSize must be"
1439 " >= 1 (%d)\n", name_, requests_queue_size);
1442 if (transfers_queue_size < 1) {
1443 fatal(
"%s: executeLSQTransfersQueueSize must be"
1444 " >= 1 (%d)\n", name_, transfers_queue_size);
1447 if (store_buffer_size < 1) {
1448 fatal(
"%s: executeLSQStoreBufferSize must be"
1449 " >= 1 (%d)\n", name_, store_buffer_size);
1495 if (request->
inst->id == inst->id) {
1498 bool to_store_buffer = request->
state ==
1501 if ((complete && !(request->
isBarrier() && !can_store)) ||
1502 (to_store_buffer && can_store))
1510 DPRINTF(MinorMem,
"Found matching memory response for inst: %s\n",
1513 DPRINTF(MinorMem,
"No matching memory response for inst: %s\n",
1534 DPRINTF(MinorMem,
"Deleting %s request: %s\n",
1535 (response->
isLoad ?
"load" :
"store"),
1547 DPRINTF(MinorMem,
"Sending store: %s to store buffer\n",
1550 request->
inst->inStoreBuffer =
true;
1572 ret = have_translated_requests ||
1577 DPRINTF(Activity,
"Need to tick\n");
1588 assert(inst->translationFault ==
NoFault || inst->inLSQ);
1591 return inst->translationFault;
1596 if (needs_burst && inst->staticInst->isAtomic()) {
1604 panic(
"Do not expect cross-cache-line atomic memory request\n");
1611 uint8_t *request_data = NULL;
1613 DPRINTF(MinorMem,
"Pushing request (%s) addr: 0x%x size: %d flags:"
1614 " 0x%x%s lineWidth : 0x%x\n",
1615 (isLoad ?
"load" :
"store/atomic"),
addr, size,
flags,
1616 (needs_burst ?
" (needs burst)" :
""),
lineWidth);
1621 request_data =
new uint8_t[size];
1622 if (inst->staticInst->isAtomic() ||
1625 std::memset(request_data, 0, size);
1627 std::memcpy(request_data,
data, size);
1633 *
this, inst, isLoad, request_data, res);
1636 *
this, inst, isLoad, request_data, res);
1639 if (inst->traceData)
1640 inst->traceData->setMem(
addr, size,
flags);
1642 int cid =
cpu.
threads[inst->id.threadId]->getTC()->contextId();
1643 request->
request->setContext(cid);
1647 inst->pc->instAddr(), std::move(amo_op));
1648 request->
request->setByteEnable(byte_enable);
1653 assert(!request->
request->isLocalAccess());
1654 request->
request->setLocalAccessor(
1662 return inst->translationFault;
1676 " lastMemBarrier=%d\n",
1685 unsigned int store_buffer_size,
1686 unsigned int store_limit_per_cycle) :
1687 Named(name_), lsq(lsq_),
1688 numSlots(store_buffer_size),
1689 storeLimitPerCycle(store_limit_per_cycle),
1691 numUnissuedAccesses(0)
1707 }
else if (!request->isCacheMaintenance()) {
1719 assert(inst->isInst() && inst->staticInst->isFullMemBarrier());
1731 assert(inst->translationFault ==
NoFault);
1749 os <<
"MemoryRunning";
1752 os <<
"MemoryNeedsRetry";
1755 os <<
"MemoryState-" <<
static_cast<int>(
state);
1791 if (tid != req_tid) {
#define DPRINTFS(x, s,...)
RequestorID dataRequestorId() const
Reads this CPU's unique data requestor ID.
AddressMonitor * getCpuAddrMonitor(ThreadID tid)
virtual ThreadContext * getContext(int tn)
Given a thread num get tho thread context for it.
ThreadID numThreads
Number of threads we're actually simulating (<= SMT_MAX_THREADS).
ThreadID contextToThread(ContextID cid)
Convert ContextID to threadID.
virtual void handleLockedRead(const RequestPtr &req)
virtual bool handleLockedWrite(const RequestPtr &req, Addr cacheBlockMask)
virtual void handleLockedSnoop(PacketPtr pkt, Addr cacheBlockMask)
virtual void translateTiming(const RequestPtr &req, ThreadContext *tc, Translation *translation, Mode mode)
Cycles is a wrapper class for representing cycle counts, i.e.
const std::string & toString() const
Return the string to a cmd given by idx.
MinorCPU is an in-order CPU model with four fixed pipeline stages:
void wakeup(ThreadID tid) override
void wakeupOnEvent(unsigned int stage_id)
Interface for stages to signal that they have become active after a callback or eventq event where th...
std::vector< minor::MinorThread * > threads
These are thread state-representing objects for this CPU.
Interface for things with names.
virtual std::string name() const
virtual PCStateBase * clone() const =0
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
static PacketPtr createWrite(const RequestPtr &req)
void makeResponse()
Take a request packet and modify it in place to be suitable for returning as a response to that reque...
T * findNextSenderState() const
Go through the sender state stack and return the first instance that is of type T (as determined by a...
void pushSenderState(SenderState *sender_state)
Push a new sender state to the packet and make the current sender state the predecessor of the new on...
SenderState * popSenderState()
Pop the top of the state stack and return a pointer to it.
T * getPtr()
get a pointer to the data ptr.
static PacketPtr createRead(const RequestPtr &req)
Constructor-like methods that return Packets based on Request objects.
RequestPtr req
A pointer to the original request.
const T * getConstPtr() const
void dataDynamic(T *p)
Set the data pointer to a value that should have delete [] called on it.
MemCmd cmd
The command field of the packet.
bool isInvalidate() const
void allocate()
Allocate memory for the packet.
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
@ NO_ACCESS
The request should not cause a memory access.
static const FlagsType STORE_NO_DATA
The SimpleThread object provides a combination of the ThreadState object and the ThreadContext interf...
const PCStateBase & pcState() const override
BaseISA * getIsaPtr() const override
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual BaseISA * getIsaPtr() const =0
virtual BaseMMU * getMMUPtr()=0
ExecContext bears the exec_context interface for Minor.
void setMemAccPredicate(bool val) override
bool instIsRightStream(MinorDynInstPtr inst)
Does the given instruction have the right stream sequence number to be committed?
bool instIsHeadInst(MinorDynInstPtr inst)
Returns true if the given instruction is at the head of the inFlightInsts instruction queue.
Request for doing barrier accounting in the store buffer.
FailedDataRequest represents requests from instructions that failed their predicates but need to ride...
Derived SenderState to carry data access info.
static AddrRangeCoverage containsAddrRangeOf(Addr req1_addr, unsigned int req1_size, Addr req2_addr, unsigned int req2_size)
Does address range req1 (req1_addr to req1_addr + req1_size - 1) fully cover, partially cover or not ...
void tryToSuppressFault()
Instructions may want to suppress translation faults (e.g.
bool needsToBeSentToStoreBuffer()
This request, once processed by the requests/transfers queues, will need to go to the store buffer.
RequestPtr request
The underlying request of this LSQRequest.
void makePacket()
Make a packet to use with the memory transaction.
bool isLoad
Load/store indication used for building packet.
void setState(LSQRequestState new_state)
Set state and output trace output.
bool issuedToMemory
This in an access other than a normal cacheable load that's visited the memory system.
void setSkipped()
Set this request as having been skipped before a memory transfer was attempt.
virtual bool sentAllPackets()=0
Have all packets been sent?
virtual PacketPtr getHeadPacket()=0
Get the next packet to issue for this request.
PacketDataPtr data
Dynamically allocated and populated data carried for building write packets.
void reportData(std::ostream &os) const
MinorTrace report interface.
virtual bool hasPacketsInMemSystem()=0
True if this request has any issued packets in the memory system and so can't be interrupted until it...
virtual void startAddrTranslation()=0
Start the address translation process for this request.
LSQRequest(LSQ &port_, MinorDynInstPtr inst_, bool isLoad_, PacketDataPtr data_=NULL, uint64_t *res_=NULL)
virtual void stepToNextPacket()=0
Step to the next packet for the next call to getHeadPacket.
MinorDynInstPtr inst
Instruction which made this request.
virtual bool isBarrier()
Is this a request a barrier?
void completeDisabledMemAccess()
bool isComplete() const
Has this request been completed.
virtual void retireResponse(PacketPtr packet_)=0
Retire a response packet into the LSQRequest packet possibly completing this transfer.
SingleDataRequest is used for requests that don't fragment.
void startAddrTranslation()
Send single translation request.
void finish(const Fault &fault_, const RequestPtr &request_, ThreadContext *tc, BaseMMU::Mode mode)
TLB interace.
void retireResponse(PacketPtr packet_)
Keep the given packet as the response packet LSQRequest::packet.
void stepToNextPacket()
Step on numIssuedFragments.
void finish(const Fault &fault_, const RequestPtr &request_, ThreadContext *tc, BaseMMU::Mode mode)
TLB response interface.
void sendNextFragmentToTranslation()
Part of the address translation loop, see startAddTranslation.
void retireResponse(PacketPtr packet_)
For loads, paste the response data into the main response packet.
void makeFragmentRequests()
Make all the Requests for this transfer's fragments so that those requests can be sent for address tr...
PacketPtr getHeadPacket()
Get the head packet as counted by numIssuedFragments.
void makeFragmentPackets()
Make the packets to go with the requests so they can be sent to the memory system.
SplitDataRequest(LSQ &port_, MinorDynInstPtr inst_, bool isLoad_, PacketDataPtr data_=NULL, uint64_t *res_=NULL)
void startAddrTranslation()
Start a loop of do { sendNextFragmentToTranslation ; translateTiming ; finish } while (numTranslatedF...
bool isDrained() const
Drained if there is absolutely nothing left in the buffer.
void step()
Try to issue more stores to memory.
AddrRangeCoverage canForwardDataToLoad(LSQRequestPtr request, unsigned int &found_slot)
Look for a store which satisfies the given load.
void forwardStoreData(LSQRequestPtr load, unsigned int slot_number)
Fill the given packet with appropriate date from slot slot_number.
void minorTrace() const
Report queue contents for MinorTrace.
StoreBuffer(std::string name_, LSQ &lsq_, unsigned int store_buffer_size, unsigned int store_limit_per_cycle)
void countIssuedStore(LSQRequestPtr request)
Count a store being issued to memory by decrementing numUnissuedAccesses.
void insert(LSQRequestPtr request)
Insert a request at the back of the queue.
unsigned int numUnissuedStores()
Number of stores in the store buffer which have not been completely issued to the memory system.
bool canInsert() const
Can a new request be inserted into the queue?
void deleteRequest(LSQRequestPtr request)
Delete the given request and free the slot it occupied.
void tryToSendToTransfers(LSQRequestPtr request)
Try and issue a memory access for a translated request at the head of the requests queue.
bool needsToTick()
May need to be ticked next cycle as one of the queues contains an actionable transfers or address tra...
void recvTimingSnoopReq(PacketPtr pkt)
void issuedMemBarrierInst(MinorDynInstPtr inst)
A memory barrier instruction has been issued, remember its execSeqNum that we can avoid issuing memor...
bool tryToSend(LSQRequestPtr request)
Try to send (or resend) a memory request's next/only packet to the memory system.
bool canSendToMemorySystem()
Can a request be sent to the memory system.
MemoryState
State of memory access for head access.
std::vector< InstSeqNum > lastMemBarrier
Most recent execSeqNum of a memory barrier instruction or 0 if there are no in-flight barriers.
unsigned int numAccessesInDTLB
Number of requests in the DTLB in the requests queue.
void sendStoreToStoreBuffer(LSQRequestPtr request)
A store has been committed, please move it to the store buffer.
void pushFailedRequest(MinorDynInstPtr inst)
Push a predicate failed-representing request into the queues just to maintain commit order.
LSQRequestPtr retryRequest
The request (from either requests or the store buffer) which is currently waiting have its memory acc...
void threadSnoop(LSQRequestPtr request)
Snoop other threads monitors on memory system accesses.
const Addr lineWidth
Memory system access width (and snap) in bytes.
AddrRangeCoverage
Coverage of one address range with another.
@ PartialAddrRangeCoverage
Fault pushRequest(MinorDynInstPtr inst, bool isLoad, uint8_t *data, unsigned int size, Addr addr, Request::Flags flags, uint64_t *res, AtomicOpFunctorPtr amo_op, const std::vector< bool > &byte_enable=std::vector< bool >())
Single interface for readMem/writeMem/amoMem to issue requests into the LSQ.
unsigned int numAccessesInMemorySystem
Count of the number of mem.
unsigned int numAccessesIssuedToMemory
The number of accesses which have been issued to the memory system but have not been committed/discar...
LSQ(std::string name_, std::string dcache_port_name_, MinorCPU &cpu_, Execute &execute_, unsigned int max_accesses_in_memory_system, unsigned int line_width, unsigned int requests_queue_size, unsigned int transfers_queue_size, unsigned int store_buffer_size, unsigned int store_buffer_cycle_store_limit)
const unsigned int inMemorySystemLimit
Maximum number of in-flight accesses issued to the memory system.
LSQQueue requests
requests contains LSQRequests which have been issued to the TLB by calling ExecContext::readMem/write...
unsigned int numStoresInTransfers
The number of stores in the transfers queue.
friend std::ostream & operator<<(std::ostream &os, MemoryState state)
Print MemoryState values as shown in the enum definition.
void step()
Step checks the queues to see if their are issuable transfers which were not otherwise picked up by t...
MemoryState state
Retry state of last issued memory transfer.
LSQQueue transfers
Once issued to memory (or, for stores, just had their state changed to StoreToStoreBuffer) LSQRequest...
void completeMemBarrierInst(MinorDynInstPtr inst, bool committed)
Complete a barrier instruction.
Addr cacheBlockMask
Address Mask for a cache block (e.g.
void popResponse(LSQRequestPtr response)
Sanity check and pop the head response.
MinorCPU & cpu
My owner(s)
void moveFromRequestsToTransfers(LSQRequestPtr request)
Move a request between queues.
LSQRequestPtr findResponse(MinorDynInstPtr inst)
Returns a response if it's at the head of the transfers queue and it's either complete or can be sent...
bool isDrained()
Is there nothing left in the LSQ.
bool recvTimingResp(PacketPtr pkt)
Memory interface.
void clearMemBarrier(MinorDynInstPtr inst)
Clear a barrier (if it's the last one marked up in lastMemBarrier)
bool empty() const
Is the queue empty?
void pop()
Pop the head item.
unsigned int unreservedRemainingSpace() const
Like remainingSpace but does not count reserved spaces.
ElemType & front()
Head value.
void push(ElemType &data)
Push an element into the buffer if it isn't a bubble.
All the fun of executing instructions from Decode and sending branch/new instruction stream info.
std::unique_ptr< AtomicOpFunctor > AtomicOpFunctorPtr
#define panic(...)
This implements a cprintf based panic() function.
#define fatal(...)
This implements a cprintf based fatal() function.
ExecContext bears the exec_context interface for Minor.
A load/store queue that allows outstanding reads and writes.
PacketPtr makePacketForRequest(const RequestPtr &request, bool isLoad, Packet::SenderState *sender_state, PacketDataPtr data)
Make a suitable packet for the given request.
void minorTrace(const char *fmt, Args ...args)
DPRINTFN for MinorTrace reporting.
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
std::shared_ptr< FaultBase > Fault
int16_t ThreadID
Thread index/ID type.
T safe_cast(U &&ref_or_ptr)
std::shared_ptr< Request > RequestPtr
Tick curTick()
The universal simulation clock.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Addr addrBlockOffset(Addr addr, Addr block_size)
Calculates the offset of a given address wrt aligned fixed-size blocks.
bool transferNeedsBurst(Addr addr, unsigned int size, unsigned int block_size)
Returns true if the given memory access (address, size) needs to be fragmented across aligned fixed-s...
constexpr decltype(nullptr) NoFault
bool isAnyActiveElement(const std::vector< bool >::const_iterator &it_start, const std::vector< bool >::const_iterator &it_end)
Test if there is any active element in an enablement range.
Minor contains all the definitions within the MinorCPU apart from the CPU class itself.
The constructed pipeline.
bool doMonitor(PacketPtr pkt)
A virtual base opaque structure used to hold state associated with the packet (e.g....