gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
lsq.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-2014 ARM Limited
3  * All rights reserved
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions are
16  * met: redistributions of source code must retain the above copyright
17  * notice, this list of conditions and the following disclaimer;
18  * redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in the
20  * documentation and/or other materials provided with the distribution;
21  * neither the name of the copyright holders nor the names of its
22  * contributors may be used to endorse or promote products derived from
23  * this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  *
37  * Authors: Andrew Bardsley
38  */
39 
40 #include "cpu/minor/lsq.hh"
41 
42 #include <iomanip>
43 #include <sstream>
44 
45 #include "arch/locked_mem.hh"
46 #include "arch/mmapped_ipr.hh"
47 #include "cpu/minor/cpu.hh"
49 #include "cpu/minor/execute.hh"
50 #include "cpu/minor/pipeline.hh"
51 #include "debug/Activity.hh"
52 #include "debug/MinorMem.hh"
53 
54 namespace Minor
55 {
56 
58 static Addr
59 addrBlockOffset(Addr addr, unsigned int block_size)
60 {
61  return addr & (block_size - 1);
62 }
63 
66 static bool
67 transferNeedsBurst(Addr addr, unsigned int size, unsigned int block_size)
68 {
69  return (addrBlockOffset(addr, block_size) + size) > block_size;
70 }
71 
72 LSQ::LSQRequest::LSQRequest(LSQ &port_, MinorDynInstPtr inst_, bool isLoad_,
73  PacketDataPtr data_, uint64_t *res_) :
74  SenderState(),
75  port(port_),
76  inst(inst_),
77  isLoad(isLoad_),
78  data(data_),
79  packet(NULL),
80  request(),
81  fault(NoFault),
82  res(res_),
83  skipped(false),
84  issuedToMemory(false),
85  state(NotIssued)
86 { }
87 
90  Addr req1_addr, unsigned int req1_size,
91  Addr req2_addr, unsigned int req2_size)
92 {
93  /* 'end' here means the address of the byte just past the request
94  * blocks */
95  Addr req2_end_addr = req2_addr + req2_size;
96  Addr req1_end_addr = req1_addr + req1_size;
97 
99 
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;
104  else
106 
107  return ret;
108 }
109 
112 {
113  return containsAddrRangeOf(request.getPaddr(), request.getSize(),
114  other_request->request.getPaddr(), other_request->request.getSize());
115 }
116 
117 bool
119 {
120  return inst->isInst() && inst->staticInst->isMemBarrier();
121 }
122 
123 bool
125 {
126  return state == StoreToStoreBuffer;
127 }
128 
129 void
131 {
132  DPRINTFS(MinorMem, (&port), "Setting state from %d to %d for request:"
133  " %s\n", state, new_state, *inst);
134  state = new_state;
135 }
136 
137 bool
139 {
140  /* @todo, There is currently only one 'completed' state. This
141  * may not be a good choice */
142  return state == Complete;
143 }
144 
145 void
146 LSQ::LSQRequest::reportData(std::ostream &os) const
147 {
148  os << (isLoad ? 'R' : 'W') << ';';
149  inst->reportData(os);
150  os << ';' << state;
151 }
152 
153 std::ostream &
154 operator <<(std::ostream &os, LSQ::AddrRangeCoverage coverage)
155 {
156  switch (coverage) {
158  os << "PartialAddrRangeCoverage";
159  break;
161  os << "FullAddrRangeCoverage";
162  break;
164  os << "NoAddrRangeCoverage";
165  break;
166  default:
167  os << "AddrRangeCoverage-" << static_cast<int>(coverage);
168  break;
169  }
170  return os;
171 }
172 
173 std::ostream &
175 {
176  switch (state) {
178  os << "NotIssued";
179  break;
181  os << "InTranslation";
182  break;
184  os << "Translated";
185  break;
187  os << "Failed";
188  break;
190  os << "RequestIssuing";
191  break;
193  os << "StoreToStoreBuffer";
194  break;
196  os << "StoreInStoreBuffer";
197  break;
199  os << "StoreBufferIssuing";
200  break;
202  os << "RequestNeedsRetry";
203  break;
205  os << "StoreBufferNeedsRetry";
206  break;
208  os << "Complete";
209  break;
210  default:
211  os << "LSQRequestState-" << static_cast<int>(state);
212  break;
213  }
214  return os;
215 }
216 
217 void
219 {
220  bool is_last_barrier =
221  inst->id.execSeqNum >= lastMemBarrier[inst->id.threadId];
222 
223  DPRINTF(MinorMem, "Moving %s barrier out of store buffer inst: %s\n",
224  (is_last_barrier ? "last" : "a"), *inst);
225 
226  if (is_last_barrier)
227  lastMemBarrier[inst->id.threadId] = 0;
228 }
229 
230 void
233 {
234  fault = fault_;
235 
236  port.numAccessesInDTLB--;
237 
238  DPRINTFS(MinorMem, (&port), "Received translation response for"
239  " request: %s\n", *inst);
240 
241  makePacket();
242 
243  setState(Translated);
244  port.tryToSendToTransfers(this);
245 
246  /* Let's try and wake up the processor for the next cycle */
247  port.cpu.wakeupOnEvent(Pipeline::ExecuteStageId);
248 }
249 
250 void
252 {
253  ThreadContext *thread = port.cpu.getContext(
254  inst->id.threadId);
255 
256  port.numAccessesInDTLB++;
257 
259 
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
263  * interface */
264  thread->getDTBPtr()->translateTiming(
265  &request, thread, this, (isLoad ? BaseTLB::Read : BaseTLB::Write));
266 }
267 
268 void
270 {
271  DPRINTFS(MinorMem, (&port), "Retiring packet\n");
272  packet = packet_;
273  packetInFlight = false;
274  setState(Complete);
275 }
276 
277 void
280 {
281  fault = fault_;
282 
283  port.numAccessesInDTLB--;
284 
285  unsigned int M5_VAR_USED expected_fragment_index =
286  numTranslatedFragments;
287 
288  numInTranslationFragments--;
289  numTranslatedFragments++;
290 
291  DPRINTFS(MinorMem, (&port), "Received translation response for fragment"
292  " %d of request: %s\n", expected_fragment_index, *inst);
293 
294  assert(request_ == fragmentRequests[expected_fragment_index]);
295 
296  /* Wake up next cycle to get things going again in case the
297  * tryToSendToTransfers does take */
298  port.cpu.wakeupOnEvent(Pipeline::ExecuteStageId);
299 
300  if (fault != NoFault) {
301  /* tryToSendToTransfers will handle the fault */
302 
303  DPRINTFS(MinorMem, (&port), "Faulting translation for fragment:"
304  " %d of request: %s\n",
305  expected_fragment_index, *inst);
306 
307  setState(Translated);
308  port.tryToSendToTransfers(this);
309  } else if (numTranslatedFragments == numFragments) {
310  makeFragmentPackets();
311 
312  setState(Translated);
313  port.tryToSendToTransfers(this);
314  } else {
315  /* Avoid calling translateTiming from within ::finish */
316  assert(!translationEvent.scheduled());
317  port.cpu.schedule(translationEvent, curTick());
318  }
319 }
320 
322  bool isLoad_, PacketDataPtr data_, uint64_t *res_) :
323  LSQRequest(port_, inst_, isLoad_, data_, res_),
324  translationEvent(*this),
325  numFragments(0),
326  numInTranslationFragments(0),
327  numTranslatedFragments(0),
328  numIssuedFragments(0),
329  numRetiredFragments(0),
330  fragmentRequests(),
331  fragmentPackets()
332 {
333  /* Don't know how many elements are needed until the request is
334  * populated by the caller. */
335 }
336 
338 {
339  for (auto i = fragmentRequests.begin();
340  i != fragmentRequests.end(); i++)
341  {
342  delete *i;
343  }
344 
345  for (auto i = fragmentPackets.begin();
346  i != fragmentPackets.end(); i++)
347  {
348  delete *i;
349  }
350 }
351 
352 void
354 {
355  Addr base_addr = request.getVaddr();
356  unsigned int whole_size = request.getSize();
357  unsigned int line_width = port.lineWidth;
358 
359  unsigned int fragment_size;
360  Addr fragment_addr;
361 
362  /* Assume that this transfer is across potentially many block snap
363  * boundaries:
364  *
365  * | _|________|________|________|___ |
366  * | |0| 1 | 2 | 3 | 4 | |
367  * | |_|________|________|________|___| |
368  * | | | | | |
369  *
370  * The first transfer (0) can be up to lineWidth in size.
371  * All the middle transfers (1-3) are lineWidth in size
372  * The last transfer (4) can be from zero to lineWidth - 1 in size
373  */
374  unsigned int first_fragment_offset =
375  addrBlockOffset(base_addr, line_width);
376  unsigned int last_fragment_size =
377  addrBlockOffset(base_addr + whole_size, line_width);
378  unsigned int first_fragment_size =
379  line_width - first_fragment_offset;
380 
381  unsigned int middle_fragments_total_size =
382  whole_size - (first_fragment_size + last_fragment_size);
383 
384  assert(addrBlockOffset(middle_fragments_total_size, line_width) == 0);
385 
386  unsigned int middle_fragment_count =
387  middle_fragments_total_size / line_width;
388 
389  numFragments = 1 /* first */ + middle_fragment_count +
390  (last_fragment_size == 0 ? 0 : 1);
391 
392  DPRINTFS(MinorMem, (&port), "Dividing transfer into %d fragmentRequests."
393  " First fragment size: %d Last fragment size: %d\n",
394  numFragments, first_fragment_size,
395  (last_fragment_size == 0 ? line_width : last_fragment_size));
396 
397  assert(((middle_fragment_count * line_width) +
398  first_fragment_size + last_fragment_size) == whole_size);
399 
400  fragment_addr = base_addr;
401  fragment_size = first_fragment_size;
402 
403  /* Just past the last address in the request */
404  Addr end_addr = base_addr + whole_size;
405 
406  for (unsigned int fragment_index = 0; fragment_index < numFragments;
407  fragment_index++)
408  {
409  bool M5_VAR_USED is_last_fragment = false;
410 
411  if (fragment_addr == base_addr) {
412  /* First fragment */
413  fragment_size = first_fragment_size;
414  } else {
415  if ((fragment_addr + line_width) > end_addr) {
416  /* Adjust size of last fragment */
417  fragment_size = end_addr - fragment_addr;
418  is_last_fragment = true;
419  } else {
420  /* Middle fragments */
421  fragment_size = line_width;
422  }
423  }
424 
425  Request *fragment = new Request();
426 
427  fragment->setContext(request.contextId());
428  fragment->setVirt(0 /* asid */,
429  fragment_addr, fragment_size, request.getFlags(),
430  request.masterId(),
431  request.getPC());
432 
433  DPRINTFS(MinorMem, (&port), "Generating fragment addr: 0x%x size: %d"
434  " (whole request addr: 0x%x size: %d) %s\n",
435  fragment_addr, fragment_size, base_addr, whole_size,
436  (is_last_fragment ? "last fragment" : ""));
437 
438  fragment_addr += fragment_size;
439 
440  fragmentRequests.push_back(fragment);
441  }
442 }
443 
444 void
446 {
447  Addr base_addr = request.getVaddr();
448 
449  DPRINTFS(MinorMem, (&port), "Making packets for request: %s\n", *inst);
450 
451  for (unsigned int fragment_index = 0; fragment_index < numFragments;
452  fragment_index++)
453  {
454  Request *fragment = fragmentRequests[fragment_index];
455 
456  DPRINTFS(MinorMem, (&port), "Making packet %d for request: %s"
457  " (%d, 0x%x)\n",
458  fragment_index, *inst,
459  (fragment->hasPaddr() ? "has paddr" : "no paddr"),
460  (fragment->hasPaddr() ? fragment->getPaddr() : 0));
461 
462  Addr fragment_addr = fragment->getVaddr();
463  unsigned int fragment_size = fragment->getSize();
464 
465  uint8_t *request_data = NULL;
466 
467  if (!isLoad) {
468  /* Split data for Packets. Will become the property of the
469  * outgoing Packets */
470  request_data = new uint8_t[fragment_size];
471  std::memcpy(request_data, data + (fragment_addr - base_addr),
472  fragment_size);
473  }
474 
475  assert(fragment->hasPaddr());
476 
477  PacketPtr fragment_packet =
478  makePacketForRequest(*fragment, isLoad, this, request_data);
479 
480  fragmentPackets.push_back(fragment_packet);
481  /* Accumulate flags in parent request */
482  request.setFlags(fragment->getFlags());
483  }
484 
485  /* Might as well make the overall/response packet here */
486  /* Get the physical address for the whole request/packet from the first
487  * fragment */
488  request.setPaddr(fragmentRequests[0]->getPaddr());
489  makePacket();
490 }
491 
492 void
494 {
496 
497  makeFragmentRequests();
498 
499  numInTranslationFragments = 0;
500  numTranslatedFragments = 0;
501 
502  /* @todo, just do these in sequence for now with
503  * a loop of:
504  * do {
505  * sendNextFragmentToTranslation ; translateTiming ; finish
506  * } while (numTranslatedFragments != numFragments);
507  */
508 
509  /* Do first translation */
510  sendNextFragmentToTranslation();
511 }
512 
513 PacketPtr
515 {
516  assert(numIssuedFragments < numFragments);
517 
518  return fragmentPackets[numIssuedFragments];
519 }
520 
521 void
523 {
524  assert(numIssuedFragments < numFragments);
525 
526  numIssuedFragments++;
527 }
528 
529 void
531 {
532  assert(numRetiredFragments < numFragments);
533 
534  DPRINTFS(MinorMem, (&port), "Retiring fragment addr: 0x%x size: %d"
535  " offset: 0x%x (retired fragment num: %d) %s\n",
536  response->req->getVaddr(), response->req->getSize(),
537  request.getVaddr() - response->req->getVaddr(),
538  numRetiredFragments,
539  (fault == NoFault ? "" : fault->name()));
540 
541  numRetiredFragments++;
542 
543  if (skipped) {
544  /* Skip because we already knew the request had faulted or been
545  * skipped */
546  DPRINTFS(MinorMem, (&port), "Skipping this fragment\n");
547  } else if (response->isError()) {
548  /* Mark up the error and leave to execute to handle it */
549  DPRINTFS(MinorMem, (&port), "Fragment has an error, skipping\n");
550  setSkipped();
551  packet->copyError(response);
552  } else {
553  if (isLoad) {
554  if (!data) {
555  /* For a split transfer, a Packet must be constructed
556  * to contain all returning data. This is that packet's
557  * data */
558  data = new uint8_t[request.getSize()];
559  }
560 
561  /* Populate the portion of the overall response data represented
562  * by the response fragment */
563  std::memcpy(
564  data + (response->req->getVaddr() - request.getVaddr()),
565  response->getConstPtr<uint8_t>(),
566  response->req->getSize());
567  }
568  }
569 
570  /* Complete early if we're skipping are no more in-flight accesses */
571  if (skipped && !hasPacketsInMemSystem()) {
572  DPRINTFS(MinorMem, (&port), "Completed skipped burst\n");
573  setState(Complete);
574  if (packet->needsResponse())
575  packet->makeResponse();
576  }
577 
578  if (numRetiredFragments == numFragments)
579  setState(Complete);
580 
581  if (!skipped && isComplete()) {
582  DPRINTFS(MinorMem, (&port), "Completed burst %d\n", packet != NULL);
583 
584  DPRINTFS(MinorMem, (&port), "Retired packet isRead: %d isWrite: %d"
585  " needsResponse: %d packetSize: %s requestSize: %s responseSize:"
586  " %s\n", packet->isRead(), packet->isWrite(),
587  packet->needsResponse(), packet->getSize(), request.getSize(),
588  response->getSize());
589 
590  /* A request can become complete by several paths, this is a sanity
591  * check to make sure the packet's data is created */
592  if (!data) {
593  data = new uint8_t[request.getSize()];
594  }
595 
596  if (isLoad) {
597  DPRINTFS(MinorMem, (&port), "Copying read data\n");
598  std::memcpy(packet->getPtr<uint8_t>(), data, request.getSize());
599  }
600  packet->makeResponse();
601  }
602 
603  /* Packets are all deallocated together in ~SplitLSQRequest */
604 }
605 
606 void
608 {
609  unsigned int fragment_index = numTranslatedFragments;
610 
611  ThreadContext *thread = port.cpu.getContext(
612  inst->id.threadId);
613 
614  DPRINTFS(MinorMem, (&port), "Submitting DTLB request for fragment: %d\n",
615  fragment_index);
616 
617  port.numAccessesInDTLB++;
618  numInTranslationFragments++;
619 
620  thread->getDTBPtr()->translateTiming(
621  fragmentRequests[fragment_index], thread, this, (isLoad ?
623 }
624 
625 bool
627 {
628  /* @todo, support store amalgamation */
629  return slots.size() < numSlots;
630 }
631 
632 void
634 {
635  auto found = std::find(slots.begin(), slots.end(), request);
636 
637  if (found != slots.end()) {
638  DPRINTF(MinorMem, "Deleting request: %s %s %s from StoreBuffer\n",
639  request, *found, *(request->inst));
640  slots.erase(found);
641 
642  delete request;
643  }
644 }
645 
646 void
648 {
649  if (!canInsert()) {
650  warn("%s: store buffer insertion without space to insert from"
651  " inst: %s\n", name(), *(request->inst));
652  }
653 
654  DPRINTF(MinorMem, "Pushing store: %s into store buffer\n", request);
655 
656  numUnissuedAccesses++;
657 
658  if (request->state != LSQRequest::Complete)
660 
661  slots.push_back(request);
662 
663  /* Let's try and wake up the processor for the next cycle to step
664  * the store buffer */
665  lsq.cpu.wakeupOnEvent(Pipeline::ExecuteStageId);
666 }
667 
670  unsigned int &found_slot)
671 {
672  unsigned int slot_index = slots.size() - 1;
673  auto i = slots.rbegin();
675 
676  /* Traverse the store buffer in reverse order (most to least recent)
677  * and try to find a slot whose address range overlaps this request */
678  while (ret == NoAddrRangeCoverage && i != slots.rend()) {
679  LSQRequestPtr slot = *i;
680 
681  if (slot->packet &&
682  slot->inst->id.threadId == request->inst->id.threadId) {
683  AddrRangeCoverage coverage = slot->containsAddrRangeOf(request);
684 
685  if (coverage != NoAddrRangeCoverage) {
686  DPRINTF(MinorMem, "Forwarding: slot: %d result: %s thisAddr:"
687  " 0x%x thisSize: %d slotAddr: 0x%x slotSize: %d\n",
688  slot_index, coverage,
689  request->request.getPaddr(), request->request.getSize(),
690  slot->request.getPaddr(), slot->request.getSize());
691 
692  found_slot = slot_index;
693  ret = coverage;
694  }
695  }
696 
697  i++;
698  slot_index--;
699  }
700 
701  return ret;
702 }
703 
705 void
707  unsigned int slot_number)
708 {
709  assert(slot_number < slots.size());
710  assert(load->packet);
711  assert(load->isLoad);
712 
713  LSQRequestPtr store = slots[slot_number];
714 
715  assert(store->packet);
716  assert(store->containsAddrRangeOf(load) == FullAddrRangeCoverage);
717 
718  Addr load_addr = load->request.getPaddr();
719  Addr store_addr = store->request.getPaddr();
720  Addr addr_offset = load_addr - store_addr;
721 
722  unsigned int load_size = load->request.getSize();
723 
724  DPRINTF(MinorMem, "Forwarding %d bytes for addr: 0x%x from store buffer"
725  " slot: %d addr: 0x%x addressOffset: 0x%x\n",
726  load_size, load_addr, slot_number,
727  store_addr, addr_offset);
728 
729  void *load_packet_data = load->packet->getPtr<void>();
730  void *store_packet_data = store->packet->getPtr<uint8_t>() + addr_offset;
731 
732  std::memcpy(load_packet_data, store_packet_data, load_size);
733 }
734 
735 void
737 {
738  /* Barriers are accounted for as they are cleared from
739  * the queue, not after their transfers are complete */
740  if (!request->isBarrier())
741  numUnissuedAccesses--;
742 }
743 
744 void
746 {
747  DPRINTF(MinorMem, "StoreBuffer step numUnissuedAccesses: %d\n",
748  numUnissuedAccesses);
749 
750  if (numUnissuedAccesses != 0 && lsq.state == LSQ::MemoryRunning) {
751  /* Clear all the leading barriers */
752  while (!slots.empty() &&
753  slots.front()->isComplete() && slots.front()->isBarrier())
754  {
755  LSQRequestPtr barrier = slots.front();
756 
757  DPRINTF(MinorMem, "Clearing barrier for inst: %s\n",
758  *(barrier->inst));
759 
760  numUnissuedAccesses--;
761  lsq.clearMemBarrier(barrier->inst);
762  slots.pop_front();
763 
764  delete barrier;
765  }
766 
767  auto i = slots.begin();
768  bool issued = true;
769  unsigned int issue_count = 0;
770 
771  /* Skip trying if the memory system is busy */
772  if (lsq.state == LSQ::MemoryNeedsRetry)
773  issued = false;
774 
775  /* Try to issue all stores in order starting from the head
776  * of the queue. Responses are allowed to be retired
777  * out of order */
778  while (issued &&
779  issue_count < storeLimitPerCycle &&
780  lsq.canSendToMemorySystem() &&
781  i != slots.end())
782  {
783  LSQRequestPtr request = *i;
784 
785  DPRINTF(MinorMem, "Considering request: %s, sentAllPackets: %d"
786  " state: %s\n",
787  *(request->inst), request->sentAllPackets(),
788  request->state);
789 
790  if (request->isBarrier() && request->isComplete()) {
791  /* Give up at barriers */
792  issued = false;
793  } else if (!(request->state == LSQRequest::StoreBufferIssuing &&
794  request->sentAllPackets()))
795  {
796  DPRINTF(MinorMem, "Trying to send request: %s to memory"
797  " system\n", *(request->inst));
798 
799  if (lsq.tryToSend(request)) {
800  countIssuedStore(request);
801  issue_count++;
802  } else {
803  /* Don't step on to the next store buffer entry if this
804  * one hasn't issued all its packets as the store
805  * buffer must still enforce ordering */
806  issued = false;
807  }
808  }
809  i++;
810  }
811  }
812 }
813 
814 void
816  bool committed)
817 {
818  if (committed) {
819  /* Not already sent to the store buffer as a store request? */
820  if (!inst->inStoreBuffer) {
821  /* Insert an entry into the store buffer to tick off barriers
822  * until there are none in flight */
823  storeBuffer.insert(new BarrierDataRequest(*this, inst));
824  }
825  } else {
826  /* Clear the barrier anyway if it wasn't actually committed */
827  clearMemBarrier(inst);
828  }
829 }
830 
831 void
833 {
834  unsigned int size = slots.size();
835  unsigned int i = 0;
836  std::ostringstream os;
837 
838  while (i < size) {
839  LSQRequestPtr request = slots[i];
840 
841  request->reportData(os);
842 
843  i++;
844  if (i < numSlots)
845  os << ',';
846  }
847 
848  while (i < numSlots) {
849  os << '-';
850 
851  i++;
852  if (i < numSlots)
853  os << ',';
854  }
855 
856  MINORTRACE("addr=%s num_unissued_stores=%d\n", os.str(),
857  numUnissuedAccesses);
858 }
859 
860 void
862 {
863  if (state == MemoryNeedsRetry) {
864  DPRINTF(MinorMem, "Request needs retry, not issuing to"
865  " memory until retry arrives\n");
866  return;
867  }
868 
869  if (request->state == LSQRequest::InTranslation) {
870  DPRINTF(MinorMem, "Request still in translation, not issuing to"
871  " memory\n");
872  return;
873  }
874 
875  assert(request->state == LSQRequest::Translated ||
876  request->state == LSQRequest::RequestIssuing ||
877  request->state == LSQRequest::Failed ||
878  request->state == LSQRequest::Complete);
879 
880  if (requests.empty() || requests.front() != request) {
881  DPRINTF(MinorMem, "Request not at front of requests queue, can't"
882  " issue to memory\n");
883  return;
884  }
885 
886  if (transfers.unreservedRemainingSpace() == 0) {
887  DPRINTF(MinorMem, "No space to insert request into transfers"
888  " queue\n");
889  return;
890  }
891 
892  if (request->isComplete() || request->state == LSQRequest::Failed) {
893  DPRINTF(MinorMem, "Passing a %s transfer on to transfers"
894  " queue\n", (request->isComplete() ? "completed" : "failed"));
895  request->setState(LSQRequest::Complete);
896  request->setSkipped();
898  return;
899  }
900 
901  if (!execute.instIsRightStream(request->inst)) {
902  /* Wrong stream, try to abort the transfer but only do so if
903  * there are no packets in flight */
904  if (request->hasPacketsInMemSystem()) {
905  DPRINTF(MinorMem, "Request's inst. is from the wrong stream,"
906  " waiting for responses before aborting request\n");
907  } else {
908  DPRINTF(MinorMem, "Request's inst. is from the wrong stream,"
909  " aborting request\n");
910  request->setState(LSQRequest::Complete);
911  request->setSkipped();
913  }
914  return;
915  }
916 
917  if (request->fault != NoFault) {
918  if (request->inst->staticInst->isPrefetch()) {
919  DPRINTF(MinorMem, "Not signalling fault for faulting prefetch\n");
920  }
921  DPRINTF(MinorMem, "Moving faulting request into the transfers"
922  " queue\n");
923  request->setState(LSQRequest::Complete);
924  request->setSkipped();
926  return;
927  }
928 
929  bool is_load = request->isLoad;
930  bool is_llsc = request->request.isLLSC();
931  bool is_swap = request->request.isSwap();
932  bool bufferable = !(request->request.isStrictlyOrdered() ||
933  is_llsc || is_swap);
934 
935  if (is_load) {
936  if (numStoresInTransfers != 0) {
937  DPRINTF(MinorMem, "Load request with stores still in transfers"
938  " queue, stalling\n");
939  return;
940  }
941  } else {
942  /* Store. Can it be sent to the store buffer? */
943  if (bufferable && !request->request.isMmappedIpr()) {
946  DPRINTF(MinorMem, "Moving store into transfers queue\n");
947  return;
948  }
949  }
950 
951  /* Check if this is the head instruction (and so must be executable as
952  * its stream sequence number was checked above) for loads which must
953  * not be speculatively issued and stores which must be issued here */
954  if (!bufferable) {
955  if (!execute.instIsHeadInst(request->inst)) {
956  DPRINTF(MinorMem, "Memory access not the head inst., can't be"
957  " sure it can be performed, not issuing\n");
958  return;
959  }
960 
961  unsigned int forwarding_slot = 0;
962 
963  if (storeBuffer.canForwardDataToLoad(request, forwarding_slot) !=
965  {
966  DPRINTF(MinorMem, "Memory access can receive forwarded data"
967  " from the store buffer, need to wait for store buffer to"
968  " drain\n");
969  return;
970  }
971  }
972 
973  /* True: submit this packet to the transfers queue to be sent to the
974  * memory system.
975  * False: skip the memory and push a packet for this request onto
976  * requests */
977  bool do_access = true;
978 
979  if (!is_llsc) {
980  /* Check for match in the store buffer */
981  if (is_load) {
982  unsigned int forwarding_slot = 0;
983  AddrRangeCoverage forwarding_result =
985  forwarding_slot);
986 
987  switch (forwarding_result) {
989  /* Forward data from the store buffer into this request and
990  * repurpose this request's packet into a response packet */
991  storeBuffer.forwardStoreData(request, forwarding_slot);
992  request->packet->makeResponse();
993 
994  /* Just move between queues, no access */
995  do_access = false;
996  break;
998  DPRINTF(MinorMem, "Load partly satisfied by store buffer"
999  " data. Must wait for the store to complete\n");
1000  return;
1001  break;
1002  case NoAddrRangeCoverage:
1003  DPRINTF(MinorMem, "No forwardable data from store buffer\n");
1004  /* Fall through to try access */
1005  break;
1006  }
1007  }
1008  } else {
1009  if (!canSendToMemorySystem()) {
1010  DPRINTF(MinorMem, "Can't send request to memory system yet\n");
1011  return;
1012  }
1013 
1014  SimpleThread &thread = *cpu.threads[request->inst->id.threadId];
1015 
1016  TheISA::PCState old_pc = thread.pcState();
1017  ExecContext context(cpu, thread, execute, request->inst);
1018 
1019  /* Handle LLSC requests and tests */
1020  if (is_load) {
1021  TheISA::handleLockedRead(&context, &request->request);
1022  } else {
1023  do_access = TheISA::handleLockedWrite(&context,
1024  &request->request, cacheBlockMask);
1025 
1026  if (!do_access) {
1027  DPRINTF(MinorMem, "Not perfoming a memory "
1028  "access for store conditional\n");
1029  }
1030  }
1031  thread.pcState(old_pc);
1032  }
1033 
1034  /* See the do_access comment above */
1035  if (do_access) {
1036  if (!canSendToMemorySystem()) {
1037  DPRINTF(MinorMem, "Can't send request to memory system yet\n");
1038  return;
1039  }
1040 
1041  /* Remember if this is an access which can't be idly
1042  * discarded by an interrupt */
1043  if (!bufferable && !request->issuedToMemory) {
1045  request->issuedToMemory = true;
1046  }
1047 
1048  if (tryToSend(request)) {
1049  moveFromRequestsToTransfers(request);
1050  }
1051  } else {
1052  request->setState(LSQRequest::Complete);
1053  moveFromRequestsToTransfers(request);
1054  }
1055 }
1056 
1057 bool
1059 {
1060  bool ret = false;
1061 
1062  if (!canSendToMemorySystem()) {
1063  DPRINTF(MinorMem, "Can't send request: %s yet, no space in memory\n",
1064  *(request->inst));
1065  } else {
1066  PacketPtr packet = request->getHeadPacket();
1067 
1068  DPRINTF(MinorMem, "Trying to send request: %s addr: 0x%x\n",
1069  *(request->inst), packet->req->getVaddr());
1070 
1071  /* The sender state of the packet *must* be an LSQRequest
1072  * so the response can be correctly handled */
1073  assert(packet->findNextSenderState<LSQRequest>());
1074 
1075  if (request->request.isMmappedIpr()) {
1076  ThreadContext *thread =
1077  cpu.getContext(cpu.contextToThread(
1078  request->request.contextId()));
1079 
1080  if (request->isLoad) {
1081  DPRINTF(MinorMem, "IPR read inst: %s\n", *(request->inst));
1082  TheISA::handleIprRead(thread, packet);
1083  } else {
1084  DPRINTF(MinorMem, "IPR write inst: %s\n", *(request->inst));
1085  TheISA::handleIprWrite(thread, packet);
1086  }
1087 
1088  request->stepToNextPacket();
1089  ret = request->sentAllPackets();
1090 
1091  if (!ret) {
1092  DPRINTF(MinorMem, "IPR access has another packet: %s\n",
1093  *(request->inst));
1094  }
1095 
1096  if (ret)
1097  request->setState(LSQRequest::Complete);
1098  else
1100  } else if (dcachePort.sendTimingReq(packet)) {
1101  DPRINTF(MinorMem, "Sent data memory request\n");
1102 
1104 
1105  request->stepToNextPacket();
1106 
1107  ret = request->sentAllPackets();
1108 
1109  switch (request->state) {
1112  /* Fully or partially issued a request in the transfers
1113  * queue */
1115  break;
1118  /* Fully or partially issued a request in the store
1119  * buffer */
1121  break;
1122  default:
1123  assert(false);
1124  break;
1125  }
1126 
1127  state = MemoryRunning;
1128  } else {
1129  DPRINTF(MinorMem,
1130  "Sending data memory request - needs retry\n");
1131 
1132  /* Needs to be resent, wait for that */
1134  retryRequest = request;
1135 
1136  switch (request->state) {
1140  break;
1144  break;
1145  default:
1146  assert(false);
1147  break;
1148  }
1149  }
1150  }
1151 
1152  if (ret)
1153  threadSnoop(request);
1154 
1155  return ret;
1156 }
1157 
1158 void
1160 {
1161  assert(!requests.empty() && requests.front() == request);
1162  assert(transfers.unreservedRemainingSpace() != 0);
1163 
1164  /* Need to count the number of stores in the transfers
1165  * queue so that loads know when their store buffer forwarding
1166  * results will be correct (only when all those stores
1167  * have reached the store buffer) */
1168  if (!request->isLoad)
1170 
1171  requests.pop();
1172  transfers.push(request);
1173 }
1174 
1175 bool
1177 {
1178  return state == MemoryRunning &&
1180 }
1181 
1182 bool
1184 {
1185  LSQRequestPtr request =
1186  safe_cast<LSQRequestPtr>(response->popSenderState());
1187 
1188  DPRINTF(MinorMem, "Received response packet inst: %s"
1189  " addr: 0x%x cmd: %s\n",
1190  *(request->inst), response->getAddr(),
1191  response->cmd.toString());
1192 
1194 
1195  if (response->isError()) {
1196  DPRINTF(MinorMem, "Received error response packet: %s\n",
1197  *request->inst);
1198  }
1199 
1200  switch (request->state) {
1203  /* Response to a request from the transfers queue */
1204  request->retireResponse(response);
1205 
1206  DPRINTF(MinorMem, "Has outstanding packets?: %d %d\n",
1207  request->hasPacketsInMemSystem(), request->isComplete());
1208 
1209  break;
1212  /* Response to a request from the store buffer */
1213  request->retireResponse(response);
1214 
1215  /* Remove completed requests unless they are barriers (which will
1216  * need to be removed in order */
1217  if (request->isComplete()) {
1218  if (!request->isBarrier()) {
1219  storeBuffer.deleteRequest(request);
1220  } else {
1221  DPRINTF(MinorMem, "Completed transfer for barrier: %s"
1222  " leaving the request as it is also a barrier\n",
1223  *(request->inst));
1224  }
1225  }
1226  break;
1227  default:
1228  /* Shouldn't be allowed to receive a response from another
1229  * state */
1230  assert(false);
1231  break;
1232  }
1233 
1234  /* We go to idle even if there are more things in the requests queue
1235  * as it's the job of step to actually step us on to the next
1236  * transaction */
1237 
1238  /* Let's try and wake up the processor for the next cycle */
1240 
1241  /* Never busy */
1242  return true;
1243 }
1244 
1245 void
1247 {
1248  DPRINTF(MinorMem, "Received retry request\n");
1249 
1250  assert(state == MemoryNeedsRetry);
1251 
1252  switch (retryRequest->state) {
1254  /* Retry in the requests queue */
1256  break;
1258  /* Retry in the store buffer */
1260  break;
1261  default:
1262  assert(false);
1263  }
1264 
1265  /* Set state back to MemoryRunning so that the following
1266  * tryToSend can actually send. Note that this won't
1267  * allow another transfer in as tryToSend should
1268  * issue a memory request and either succeed for this
1269  * request or return the LSQ back to MemoryNeedsRetry */
1270  state = MemoryRunning;
1271 
1272  /* Try to resend the request */
1273  if (tryToSend(retryRequest)) {
1274  /* Successfully sent, need to move the request */
1275  switch (retryRequest->state) {
1277  /* In the requests queue */
1279  break;
1281  /* In the store buffer */
1283  break;
1284  default:
1285  assert(false);
1286  break;
1287  }
1288 
1289  retryRequest = NULL;
1290  }
1291 }
1292 
1293 LSQ::LSQ(std::string name_, std::string dcache_port_name_,
1294  MinorCPU &cpu_, Execute &execute_,
1295  unsigned int in_memory_system_limit, unsigned int line_width,
1296  unsigned int requests_queue_size, unsigned int transfers_queue_size,
1297  unsigned int store_buffer_size,
1298  unsigned int store_buffer_cycle_store_limit) :
1299  Named(name_),
1300  cpu(cpu_),
1301  execute(execute_),
1302  dcachePort(dcache_port_name_, *this, cpu_),
1303  lastMemBarrier(cpu.numThreads, 0),
1305  inMemorySystemLimit(in_memory_system_limit),
1306  lineWidth((line_width == 0 ? cpu.cacheLineSize() : line_width)),
1307  requests(name_ + ".requests", "addr", requests_queue_size),
1308  transfers(name_ + ".transfers", "addr", transfers_queue_size),
1309  storeBuffer(name_ + ".storeBuffer",
1310  *this, store_buffer_size, store_buffer_cycle_store_limit),
1312  numAccessesInDTLB(0),
1315  retryRequest(NULL),
1316  cacheBlockMask(~(cpu_.cacheLineSize() - 1))
1317 {
1318  if (in_memory_system_limit < 1) {
1319  fatal("%s: executeMaxAccessesInMemory must be >= 1 (%d)\n", name_,
1320  in_memory_system_limit);
1321  }
1322 
1323  if (store_buffer_cycle_store_limit < 1) {
1324  fatal("%s: executeLSQMaxStoreBufferStoresPerCycle must be"
1325  " >= 1 (%d)\n", name_, store_buffer_cycle_store_limit);
1326  }
1327 
1328  if (requests_queue_size < 1) {
1329  fatal("%s: executeLSQRequestsQueueSize must be"
1330  " >= 1 (%d)\n", name_, requests_queue_size);
1331  }
1332 
1333  if (transfers_queue_size < 1) {
1334  fatal("%s: executeLSQTransfersQueueSize must be"
1335  " >= 1 (%d)\n", name_, transfers_queue_size);
1336  }
1337 
1338  if (store_buffer_size < 1) {
1339  fatal("%s: executeLSQStoreBufferSize must be"
1340  " >= 1 (%d)\n", name_, store_buffer_size);
1341  }
1342 
1343  if ((lineWidth & (lineWidth - 1)) != 0) {
1344  fatal("%s: lineWidth: %d must be a power of 2\n", name(), lineWidth);
1345  }
1346 }
1347 
1349 { }
1350 
1352 {
1353  if (packet)
1354  delete packet;
1355  if (data)
1356  delete [] data;
1357 }
1358 
1365 void
1367 {
1368  /* Try to move address-translated requests between queues and issue
1369  * them */
1370  if (!requests.empty())
1372 
1373  storeBuffer.step();
1374 }
1375 
1378 {
1379  LSQ::LSQRequestPtr ret = NULL;
1380 
1381  if (!transfers.empty()) {
1382  LSQRequestPtr request = transfers.front();
1383 
1384  /* Same instruction and complete access or a store that's
1385  * capable of being moved to the store buffer */
1386  if (request->inst->id == inst->id) {
1387  bool complete = request->isComplete();
1388  bool can_store = storeBuffer.canInsert();
1389  bool to_store_buffer = request->state ==
1391 
1392  if ((complete && !(request->isBarrier() && !can_store)) ||
1393  (to_store_buffer && can_store))
1394  {
1395  ret = request;
1396  }
1397  }
1398  }
1399 
1400  if (ret) {
1401  DPRINTF(MinorMem, "Found matching memory response for inst: %s\n",
1402  *inst);
1403  } else {
1404  DPRINTF(MinorMem, "No matching memory response for inst: %s\n",
1405  *inst);
1406  }
1407 
1408  return ret;
1409 }
1410 
1411 void
1413 {
1414  assert(!transfers.empty() && transfers.front() == response);
1415 
1416  transfers.pop();
1417 
1418  if (!response->isLoad)
1420 
1421  if (response->issuedToMemory)
1423 
1424  if (response->state != LSQRequest::StoreInStoreBuffer) {
1425  DPRINTF(MinorMem, "Deleting %s request: %s\n",
1426  (response->isLoad ? "load" : "store"),
1427  *(response->inst));
1428 
1429  delete response;
1430  }
1431 }
1432 
1433 void
1435 {
1436  assert(request->state == LSQRequest::StoreToStoreBuffer);
1437 
1438  DPRINTF(MinorMem, "Sending store: %s to store buffer\n",
1439  *(request->inst));
1440 
1441  request->inst->inStoreBuffer = true;
1442 
1443  storeBuffer.insert(request);
1444 }
1445 
1446 bool
1448 {
1449  return requests.empty() && transfers.empty() &&
1451 }
1452 
1453 bool
1455 {
1456  bool ret = false;
1457 
1458  if (canSendToMemorySystem()) {
1459  bool have_translated_requests = !requests.empty() &&
1462 
1463  ret = have_translated_requests ||
1465  }
1466 
1467  if (ret)
1468  DPRINTF(Activity, "Need to tick\n");
1469 
1470  return ret;
1471 }
1472 
1473 void
1474 LSQ::pushRequest(MinorDynInstPtr inst, bool isLoad, uint8_t *data,
1475  unsigned int size, Addr addr, Request::Flags flags,
1476  uint64_t *res)
1477 {
1478  bool needs_burst = transferNeedsBurst(addr, size, lineWidth);
1479  LSQRequestPtr request;
1480 
1481  /* Copy given data into the request. The request will pass this to the
1482  * packet and then it will own the data */
1483  uint8_t *request_data = NULL;
1484 
1485  DPRINTF(MinorMem, "Pushing request (%s) addr: 0x%x size: %d flags:"
1486  " 0x%x%s lineWidth : 0x%x\n",
1487  (isLoad ? "load" : "store"), addr, size, flags,
1488  (needs_burst ? " (needs burst)" : ""), lineWidth);
1489 
1490  if (!isLoad) {
1491  /* request_data becomes the property of a ...DataRequest (see below)
1492  * and destroyed by its destructor */
1493  request_data = new uint8_t[size];
1494  if (flags & Request::CACHE_BLOCK_ZERO) {
1495  /* For cache zeroing, just use zeroed data */
1496  std::memset(request_data, 0, size);
1497  } else {
1498  std::memcpy(request_data, data, size);
1499  }
1500  }
1501 
1502  if (needs_burst) {
1503  request = new SplitDataRequest(
1504  *this, inst, isLoad, request_data, res);
1505  } else {
1506  request = new SingleDataRequest(
1507  *this, inst, isLoad, request_data, res);
1508  }
1509 
1510  if (inst->traceData)
1511  inst->traceData->setMem(addr, size, flags);
1512 
1513  int cid = cpu.threads[inst->id.threadId]->getTC()->contextId();
1514  request->request.setContext(cid);
1515  request->request.setVirt(0 /* asid */,
1516  addr, size, flags, cpu.dataMasterId(),
1517  /* I've no idea why we need the PC, but give it */
1518  inst->pc.instAddr());
1519 
1520  requests.push(request);
1521  request->startAddrTranslation();
1522 }
1523 
1524 void
1526 {
1527  LSQRequestPtr request = new FailedDataRequest(*this, inst);
1528  requests.push(request);
1529 }
1530 
1531 void
1533 {
1534  MINORTRACE("state=%s in_tlb_mem=%d/%d stores_in_transfers=%d"
1535  " lastMemBarrier=%d\n",
1538  requests.minorTrace();
1541 }
1542 
1543 LSQ::StoreBuffer::StoreBuffer(std::string name_, LSQ &lsq_,
1544  unsigned int store_buffer_size,
1545  unsigned int store_limit_per_cycle) :
1546  Named(name_), lsq(lsq_),
1547  numSlots(store_buffer_size),
1548  storeLimitPerCycle(store_limit_per_cycle),
1549  slots(),
1550  numUnissuedAccesses(0)
1551 {
1552 }
1553 
1554 PacketPtr
1555 makePacketForRequest(Request &request, bool isLoad,
1556  Packet::SenderState *sender_state, PacketDataPtr data)
1557 {
1558  PacketPtr ret = isLoad ? Packet::createRead(&request)
1559  : Packet::createWrite(&request);
1560 
1561  if (sender_state)
1562  ret->pushSenderState(sender_state);
1563 
1564  if (isLoad)
1565  ret->allocate();
1566  else
1567  ret->dataDynamic(data);
1568 
1569  return ret;
1570 }
1571 
1572 void
1574 {
1575  assert(inst->isInst() && inst->staticInst->isMemBarrier());
1576  assert(inst->id.execSeqNum > lastMemBarrier[inst->id.threadId]);
1577 
1578  /* Remember the barrier. We only have a notion of one
1579  * barrier so this may result in some mem refs being
1580  * delayed if they are between barriers */
1581  lastMemBarrier[inst->id.threadId] = inst->id.execSeqNum;
1582 }
1583 
1584 void
1586 {
1587  /* Make the function idempotent */
1588  if (packet)
1589  return;
1590 
1591  // if the translation faulted, do not create a packet
1592  if (fault != NoFault) {
1593  assert(packet == NULL);
1594  return;
1595  }
1596 
1597  packet = makePacketForRequest(request, isLoad, this, data);
1598  /* Null the ret data so we know not to deallocate it when the
1599  * ret is destroyed. The data now belongs to the ret and
1600  * the ret is responsible for its destruction */
1601  data = NULL;
1602 }
1603 
1604 std::ostream &
1606 {
1607  switch (state) {
1608  case LSQ::MemoryRunning:
1609  os << "MemoryRunning";
1610  break;
1611  case LSQ::MemoryNeedsRetry:
1612  os << "MemoryNeedsRetry";
1613  break;
1614  default:
1615  os << "MemoryState-" << static_cast<int>(state);
1616  break;
1617  }
1618  return os;
1619 }
1620 
1621 void
1623 {
1624  /* LLSC operations in Minor can't be speculative and are executed from
1625  * the head of the requests queue. We shouldn't need to do more than
1626  * this action on snoops. */
1627  for (ThreadID tid = 0; tid < cpu.numThreads; tid++) {
1628  if (cpu.getCpuAddrMonitor(tid)->doMonitor(pkt)) {
1629  cpu.wakeup(tid);
1630  }
1631  }
1632 
1633  if (pkt->isInvalidate() || pkt->isWrite()) {
1634  for (ThreadID tid = 0; tid < cpu.numThreads; tid++) {
1635  TheISA::handleLockedSnoop(cpu.getContext(tid), pkt,
1636  cacheBlockMask);
1637  }
1638  }
1639 }
1640 
1641 void
1643 {
1644  /* LLSC operations in Minor can't be speculative and are executed from
1645  * the head of the requests queue. We shouldn't need to do more than
1646  * this action on snoops. */
1647  ThreadID req_tid = request->inst->id.threadId;
1648  PacketPtr pkt = request->packet;
1649 
1650  for (ThreadID tid = 0; tid < cpu.numThreads; tid++) {
1651  if (tid != req_tid) {
1652  if (cpu.getCpuAddrMonitor(tid)->doMonitor(pkt)) {
1653  cpu.wakeup(tid);
1654  }
1655 
1656  if (pkt->isInvalidate() || pkt->isWrite()) {
1657  TheISA::handleLockedSnoop(cpu.getContext(tid), pkt,
1658  cacheBlockMask);
1659  }
1660  }
1661  }
1662 }
1663 
1664 }
MemoryState
State of memory access for head access.
Definition: lsq.hh:70
#define DPRINTF(x,...)
Definition: trace.hh:212
DcachePort dcachePort
Definition: lsq.hh:114
void makeFragmentPackets()
Make the packets to go with the requests so they can be sent to the memory system.
Definition: lsq.cc:445
virtual bool sentAllPackets()=0
Have all packets been sent?
void setState(LSQRequestState new_state)
Set state and output trace output.
Definition: lsq.cc:130
MinorDynInstPtr inst
Instruction which made this request.
Definition: lsq.hh:129
SingleDataRequest is used for requests that don't fragment.
Definition: lsq.hh:332
const std::string & name() const
Definition: trace.hh:149
unsigned int numAccessesIssuedToMemory
The number of accesses which have been issued to the memory system but have not been committed/discar...
Definition: lsq.hh:614
decltype(nullptr) constexpr NoFault
Definition: types.hh:189
Execute stage.
Definition: execute.hh:62
void pop()
Pop the head item.
Definition: buffers.hh:497
LSQQueue transfers
Once issued to memory (or, for stores, just had their state changed to StoreToStoreBuffer) LSQRequest...
Definition: lsq.hh:582
Top level definition of the Minor in-order CPU model.
PacketDataPtr data
Dynamically allocated and populated data carried for building write packets.
Definition: lsq.hh:137
void makeFragmentRequests()
Make all the Requests for this transfer's fragments so that those requests can be sent for address tr...
Definition: lsq.cc:353
StoreBuffer(std::string name_, LSQ &lsq_, unsigned int store_buffer_size, unsigned int store_limit_per_cycle)
Definition: lsq.cc:1543
LSQQueue requests
requests contains LSQRequests which have been issued to the TLB by calling ExecContext::readMem/write...
Definition: lsq.hh:573
friend std::ostream & operator<<(std::ostream &os, MemoryState state)
Print MemoryState values as shown in the enum definition.
Definition: lsq.cc:1605
void finish(const Fault &fault_, RequestPtr request_, ThreadContext *tc, BaseTLB::Mode mode)
TLB interace.
Definition: lsq.cc:231
Bitfield< 7 > i
Definition: miscregs.hh:1378
ContextID contextId() const
Accessor function for context ID.
Definition: request.hh:694
void step()
Try to issue more stores to memory.
Definition: lsq.cc:745
bool isStrictlyOrdered() const
Definition: request.hh:768
void popResponse(LSQRequestPtr response)
Sanity check and pop the head response.
Definition: lsq.cc:1412
void issuedMemBarrierInst(MinorDynInstPtr inst)
A memory barrier instruction has been issued, remember its execSeqNum that we can avoid issuing memor...
Definition: lsq.cc:1573
void makePacket()
Make a packet to use with the memory transaction.
Definition: lsq.cc:1585
bool instIsHeadInst(MinorDynInstPtr inst)
Returns true if the given instruction is at the head of the inFlightInsts instruction queue...
Definition: execute.cc:1850
void finish(const Fault &fault_, RequestPtr request_, ThreadContext *tc, BaseTLB::Mode mode)
TLB response interface.
Definition: lsq.cc:278
void pushFailedRequest(MinorDynInstPtr inst)
Push a predicate failed-representing request into the queues just to maintain commit order...
Definition: lsq.cc:1525
All the fun of executing instructions from Decode and sending branch/new instruction stream info...
void wakeupOnEvent(unsigned int stage_id)
Interface for stages to signal that they have become active after a callback or eventq event where th...
Definition: cpu.cc:305
unsigned int numStoresInTransfers
The number of stores in the transfers queue.
Definition: lsq.hh:609
uint8_t * PacketDataPtr
Definition: packet.hh:70
Fault fault
Fault generated performing this request.
Definition: lsq.hh:149
ip6_addr_t addr
Definition: inet.hh:335
bool isWrite() const
Definition: packet.hh:503
PacketPtr makePacketForRequest(Request &request, bool isLoad, Packet::SenderState *sender_state, PacketDataPtr data)
Make a suitable packet for the given request.
Definition: lsq.cc:1555
virtual bool isBarrier()
Is this a request a barrier?
Definition: lsq.cc:118
bool isMmappedIpr() const
Definition: request.hh:776
void minorTrace() const
Report queue contents for MinorTrace.
Definition: lsq.cc:832
bool handleLockedWrite(XC *xc, Request *req, Addr cacheBlockMask)
Definition: locked_mem.hh:102
PacketPtr getHeadPacket()
Get the head packet as counted by numIssuedFragments.
Definition: lsq.cc:514
void setContext(ContextID context_id)
Set up Context numbers.
Definition: request.hh:449
The SimpleThread object provides a combination of the ThreadState object and the ThreadContext interf...
void retireResponse(PacketPtr packet_)
For loads, paste the response data into the main response packet.
Definition: lsq.cc:530
This is a write that is targeted and zeroing an entire cache block.
Definition: request.hh:134
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the slave port by calling its corresponding receive function...
Definition: port.cc:180
Bitfield< 4, 0 > mode
Definition: miscregs.hh:1385
unsigned int numAccessesInMemorySystem
Count of the number of mem.
Definition: lsq.hh:602
unsigned int unreservedRemainingSpace() const
Like remainingSpace but does not count reserved spaces.
Definition: buffers.hh:484
void reportData(std::ostream &os) const
MinorTrace report interface.
Definition: lsq.cc:146
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...
Definition: lsq.cc:1377
void sendNextFragmentToTranslation()
Part of the address translation loop, see startAddTranslation.
Definition: lsq.cc:607
Cycles handleIprRead(ThreadContext *xc, Packet *pkt)
Helper function to handle IPRs when the target architecture doesn't need its own IPR handling...
Definition: mmapped_ipr.hh:139
Cycles handleIprWrite(ThreadContext *xc, Packet *pkt)
Helper function to handle IPRs when the target architecture doesn't need its own IPR handling...
Definition: mmapped_ipr.hh:160
ThreadContext is the external interface to all thread state for anything outside of the CPU...
T * getPtr()
get a pointer to the data ptr.
Definition: packet.hh:959
ExecContext bears the exec_context interface for Minor.
Definition: exec_context.hh:74
struct ip6_opt_fragment fragment
Definition: inet.hh:336
Bitfield< 17 > os
Definition: misc.hh:804
ExecContext bears the exec_context interface for Minor.
Derived SenderState to carry data access info.
Definition: lsq.hh:120
LSQRequestState state
Definition: lsq.hh:185
bool canInsert() const
Can a new request be inserted into the queue?
Definition: lsq.cc:626
#define DPRINTFS(x,...)
Definition: trace.hh:213
const char data[]
Definition: circlebuf.cc:43
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 ...
Definition: lsq.cc:89
#define warn(...)
Definition: misc.hh:219
void handleLockedSnoop(XC *xc, PacketPtr pkt, Addr cacheBlockMask)
Definition: locked_mem.hh:69
std::vector< InstSeqNum > lastMemBarrier
Most recent execSeqNum of a memory barrier instruction or 0 if there are no in-flight barriers...
Definition: lsq.hh:540
Definition: trace.hh:140
void pushRequest(MinorDynInstPtr inst, bool isLoad, uint8_t *data, unsigned int size, Addr addr, Request::Flags flags, uint64_t *res)
Single interface for readMem/writeMem to issue requests into the LSQ.
Definition: lsq.cc:1474
static Addr addrBlockOffset(Addr addr, unsigned int block_size)
Returns the offset of addr into an aligned a block of size block_size.
Definition: lsq.cc:59
Request for doing barrier accounting in the store buffer.
Definition: lsq.hh:320
void completeMemBarrierInst(MinorDynInstPtr inst, bool committed)
Complete a barrier instruction.
Definition: lsq.cc:815
Request request
The underlying request of this LSQRequest.
Definition: lsq.hh:146
Tick curTick()
The current simulated tick.
Definition: core.hh:47
bool empty() const
Is the queue empty?
Definition: buffers.hh:500
MemoryState state
Retry state of last issued memory transfer.
Definition: lsq.hh:544
virtual ~LSQRequest()
Definition: lsq.cc:1351
bool isLLSC() const
Definition: request.hh:771
ElemType & front()
Head value.
Definition: buffers.hh:492
StoreBuffer storeBuffer
Definition: lsq.hh:593
virtual TheISA::TLB * getDTBPtr()=0
void startAddrTranslation()
Start a loop of do { sendNextFragmentToTranslation ; translateTiming ; finish } while (numTranslatedF...
Definition: lsq.cc:493
bool issuedToMemory
This in an access other than a normal cacheable load that's visited the memory system.
Definition: lsq.hh:161
virtual void retireResponse(PacketPtr packet_)=0
Retire a response packet into the LSQRequest packet possibly completing this transfer.
bool tryToSend(LSQRequestPtr request)
Try to send (or resend) a memory request's next/only packet to the memory system. ...
Definition: lsq.cc:1058
bool isLoad
Load/store indication used for building packet.
Definition: lsq.hh:133
Addr getPaddr() const
Definition: request.hh:519
#define fatal(...)
Definition: misc.hh:163
virtual void stepToNextPacket()=0
Step to the next packet for the next call to getHeadPacket.
const RequestPtr req
A pointer to the original request.
Definition: packet.hh:304
static bool transferNeedsBurst(Addr addr, unsigned int size, unsigned int block_size)
Returns true if the given [addr .
Definition: lsq.cc:67
bool canSendToMemorySystem()
Can a request be sent to the memory system.
Definition: lsq.cc:1176
virtual void startAddrTranslation()=0
Start the address translation process for this request.
bool isDrained() const
Drained if there is absolutely nothing left in the buffer.
Definition: lsq.hh:527
FailedDataRequest represents requests from instructions that failed their predicates but need to ride...
Definition: lsq.hh:310
AddrRangeCoverage canForwardDataToLoad(LSQRequestPtr request, unsigned int &found_slot)
Look for a store which satisfies the given load.
Definition: lsq.cc:669
bool needsToBeSentToStoreBuffer()
This request, once processed by the requests/transfers queues, will need to go to the store buffer...
Definition: lsq.cc:124
void clearMemBarrier(MinorDynInstPtr inst)
Clear a barrier (if it's the last one marked up in lastMemBarrier)
Definition: lsq.cc:218
bool isSwap() const
Definition: request.hh:774
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
MinorCPU & cpu
My owner(s)
Definition: lsq.hh:65
T safe_cast(U ptr)
Definition: cast.hh:61
bool isDrained()
Is there nothing left in the LSQ.
Definition: lsq.cc:1447
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:245
unsigned int numUnissuedStores()
Number of stores in the store buffer which have not been completely issued to the memory system...
Definition: lsq.hh:519
void tryToSendToTransfers(LSQRequestPtr request)
Try and issue a memory access for a translated request at the head of the requests queue...
Definition: lsq.cc:861
A virtual base opaque structure used to hold state associated with the packet (e.g., an MSHR), specific to a MemObject that sees the packet.
Definition: packet.hh:377
LSQRequest(LSQ &port_, MinorDynInstPtr inst_, bool isLoad_, PacketDataPtr data_=NULL, uint64_t *res_=NULL)
Definition: lsq.cc:72
AddrRangeCoverage
Coverage of one address range with another.
Definition: lsq.hh:81
void step()
Step checks the queues to see if their are issuable transfers which were not otherwise picked up by t...
Definition: lsq.cc:1366
A load/store queue that allows outstanding reads and writes.
unsigned int numAccessesInDTLB
Number of requests in the DTLB in the requests queue.
Definition: lsq.hh:605
TheISA::PCState pcState()
static const int NumArgumentRegs M5_VAR_USED
Definition: process.cc:83
Flags getFlags()
Accessor for flags.
Definition: request.hh:584
Mode
Definition: tlb.hh:61
int16_t ThreadID
Thread index/ID type.
Definition: types.hh:171
void makeResponse()
Take a request packet and modify it in place to be suitable for returning as a response to that reque...
Definition: packet.hh:845
void sendStoreToStoreBuffer(LSQRequestPtr request)
A store has been committed, please move it to the store buffer.
Definition: lsq.cc:1434
LSQRequestPtr retryRequest
The request (from either requests or the store buffer) which is currently waiting have its memory acc...
Definition: lsq.hh:618
bool recvTimingResp(PacketPtr pkt)
Memory interface.
Definition: lsq.cc:1183
int size()
Definition: pagetable.hh:146
virtual ~LSQ()
Definition: lsq.cc:1348
void insert(LSQRequestPtr request)
Insert a request at the back of the queue.
Definition: lsq.cc:647
bool instIsRightStream(MinorDynInstPtr inst)
Does the given instruction have the right stream sequence number to be committed? ...
Definition: execute.cc:1844
bool isError() const
Definition: packet.hh:528
GenericISA::SimplePCState< MachInst > PCState
Definition: types.hh:43
MemCmd cmd
The command field of the packet.
Definition: packet.hh:301
void minorTrace() const
Definition: lsq.cc:1532
Addr getVaddr() const
Definition: request.hh:616
Addr cacheBlockMask
Address Mask for a cache block (e.g.
Definition: lsq.hh:621
void wakeup(ThreadID tid) override
Definition: cpu.cc:169
PacketPtr packet
Definition: lsq.hh:143
void setVirt(int asid, Addr vaddr, unsigned size, Flags flags, MasterID mid, Addr pc)
Set up a virtual (e.g., CPU) request in a previously allocated Request object.
Definition: request.hh:460
std::vector< Minor::MinorThread * > threads
These are thread state-representing objects for this CPU.
Definition: cpu.hh:95
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)
Definition: lsq.cc:1293
void push(ElemType &data)
Push an element into the buffer if it isn't a bubble.
Definition: buffers.hh:424
#define MINORTRACE(...)
DPRINTFN for MinorTrace reporting.
Definition: trace.hh:62
const std::string & toString() const
Return the string to a cmd given by idx.
Definition: packet.hh:227
static PacketPtr createRead(const RequestPtr req)
Constructor-like methods that return Packets based on Request objects.
Definition: packet.hh:809
The constructed pipeline.
virtual PacketPtr getHeadPacket()=0
Get the next packet to issue for this request.
void dataDynamic(T *p)
Set the data pointer to a value that should have delete [] called on it.
Definition: packet.hh:947
void recvReqRetry()
Definition: lsq.cc:1246
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...
Definition: packet.cc:329
T * findNextSenderState() const
Go through the sender state stack and return the first instance that is of type T (as determined by a...
Definition: packet.hh:484
SenderState * popSenderState()
Pop the top of the state stack and return a pointer to it.
Definition: packet.cc:337
void minorTrace() const
Definition: buffers.hh:503
const T * getConstPtr() const
Definition: packet.hh:967
const unsigned int inMemorySystemLimit
Maximum number of in-flight accesses issued to the memory system.
Definition: lsq.hh:547
const unsigned int lineWidth
Memory system access width (and snap) in bytes.
Definition: lsq.hh:550
unsigned getSize() const
Definition: packet.hh:649
MinorCPU is an in-order CPU model with four fixed pipeline stages:
Definition: cpu.hh:79
bool isInvalidate() const
Definition: packet.hh:517
static PacketPtr createWrite(const RequestPtr req)
Definition: packet.hh:815
unsigned getSize() const
Definition: request.hh:552
bool isComplete() const
Has this request been completed.
Definition: lsq.cc:138
void threadSnoop(LSQRequestPtr request)
Snoop other threads monitors on memory system accesses.
Definition: lsq.cc:1642
void setSkipped()
Set this request as having been skipped before a memory transfer was attempt.
Definition: lsq.hh:206
void stepToNextPacket()
Step on numIssuedFragments.
Definition: lsq.cc:522
std::shared_ptr< FaultBase > Fault
Definition: types.hh:184
void retireResponse(PacketPtr packet_)
Keep the given packet as the response packet LSQRequest::packet.
Definition: lsq.cc:269
void startAddrTranslation()
Send single translation request.
Definition: lsq.cc:251
void allocate()
Allocate memory for the packet.
Definition: packet.hh:1082
void deleteRequest(LSQRequestPtr request)
Delete the given request and free the slot it occupied.
Definition: lsq.cc:633
void recvTimingSnoopReq(PacketPtr pkt)
Definition: lsq.cc:1622
bool hasPaddr() const
Accessor for paddr.
Definition: request.hh:513
void countIssuedStore(LSQRequestPtr request)
Count a store being issued to memory by decrementing numUnissuedAccesses.
Definition: lsq.cc:736
Execute & execute
Definition: lsq.hh:66
void handleLockedRead(XC *xc, Request *req)
Definition: locked_mem.hh:88
Addr getAddr() const
Definition: packet.hh:639
void moveFromRequestsToTransfers(LSQRequestPtr request)
Move a request between queues.
Definition: lsq.cc:1159
void forwardStoreData(LSQRequestPtr load, unsigned int slot_number)
Fill the given packet with appropriate date from slot slot_number.
Definition: lsq.cc:706
virtual bool hasPacketsInMemSystem()=0
True if this request has any issued packets in the memory system and so can't be interrupted until it...
SplitDataRequest(LSQ &port_, MinorDynInstPtr inst_, bool isLoad_, PacketDataPtr data_=NULL, uint64_t *res_=NULL)
Definition: lsq.cc:321
bool needsToTick()
May need to be ticked next cycle as one of the queues contains an actionable transfers or address tra...
Definition: lsq.cc:1454

Generated on Fri Jun 9 2017 13:03:42 for gem5 by doxygen 1.8.6