gem5  v22.1.0.0
lsq_unit.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2014, 2017-2021 ARM Limited
3  * Copyright (c) 2013 Advanced Micro Devices, Inc.
4  * All rights reserved
5  *
6  * The license below extends only to copyright in the software and shall
7  * not be construed as granting a license to any other intellectual
8  * property including but not limited to intellectual property relating
9  * to a hardware implementation of the functionality of the software
10  * licensed hereunder. You may use the software subject to the license
11  * terms below provided that you ensure that this notice is replicated
12  * unmodified and in its entirety in all distributions of the software,
13  * modified or unmodified, in source code or in binary form.
14  *
15  * Copyright (c) 2004-2006 The Regents of The University of Michigan
16  * All rights reserved.
17  *
18  * Redistribution and use in source and binary forms, with or without
19  * modification, are permitted provided that the following conditions are
20  * met: redistributions of source code must retain the above copyright
21  * notice, this list of conditions and the following disclaimer;
22  * redistributions in binary form must reproduce the above copyright
23  * notice, this list of conditions and the following disclaimer in the
24  * documentation and/or other materials provided with the distribution;
25  * neither the name of the copyright holders nor the names of its
26  * contributors may be used to endorse or promote products derived from
27  * this software without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40  */
41 
42 #include "cpu/o3/lsq_unit.hh"
43 
45 #include "base/str.hh"
46 #include "cpu/checker/cpu.hh"
47 #include "cpu/o3/dyn_inst.hh"
48 #include "cpu/o3/limits.hh"
49 #include "cpu/o3/lsq.hh"
50 #include "debug/Activity.hh"
51 #include "debug/HtmCpu.hh"
52 #include "debug/IEW.hh"
53 #include "debug/LSQUnit.hh"
54 #include "debug/O3PipeView.hh"
55 #include "mem/packet.hh"
56 #include "mem/request.hh"
57 
58 namespace gem5
59 {
60 
61 namespace o3
62 {
63 
65  PacketPtr _pkt, LSQUnit *lsq_ptr)
66  : Event(Default_Pri, AutoDelete),
67  inst(_inst), pkt(_pkt), lsqPtr(lsq_ptr)
68 {
69  assert(_inst->savedRequest);
70  _inst->savedRequest->writebackScheduled();
71 }
72 
73 void
75 {
76  assert(!lsqPtr->cpu->switchedOut());
77 
78  lsqPtr->writeback(inst, pkt);
79 
80  assert(inst->savedRequest);
81  inst->savedRequest->writebackDone();
82  delete pkt;
83 }
84 
85 const char *
87 {
88  return "Store writeback";
89 }
90 
91 bool
93 {
94  LSQRequest *request = dynamic_cast<LSQRequest*>(pkt->senderState);
95  assert(request != nullptr);
96  bool ret = true;
97  /* Check that the request is still alive before any further action. */
98  if (!request->isReleased()) {
99  ret = request->recvTimingResp(pkt);
100  }
101  return ret;
102 }
103 
104 void
106 {
107  LSQRequest *request = dynamic_cast<LSQRequest *>(pkt->senderState);
108  DynInstPtr inst = request->instruction();
109 
110  // hardware transactional memory
111  // sanity check
112  if (pkt->isHtmTransactional() && !inst->isSquashed()) {
113  assert(inst->getHtmTransactionUid() == pkt->getHtmTransactionUid());
114  }
115 
116  // if in a HTM transaction, it's possible
117  // to abort within the cache hierarchy.
118  // This is signalled back to the processor
119  // through responses to memory requests.
120  if (pkt->htmTransactionFailedInCache()) {
121  // cannot do this for write requests because
122  // they cannot tolerate faults
123  const HtmCacheFailure htm_rc =
125  if (pkt->isWrite()) {
126  DPRINTF(HtmCpu,
127  "store notification (ignored) of HTM transaction failure "
128  "in cache - addr=0x%lx - rc=%s - htmUid=%d\n",
129  pkt->getAddr(), htmFailureToStr(htm_rc),
130  pkt->getHtmTransactionUid());
131  } else {
132  HtmFailureFaultCause fail_reason =
134 
135  if (htm_rc == HtmCacheFailure::FAIL_SELF) {
136  fail_reason = HtmFailureFaultCause::SIZE;
137  } else if (htm_rc == HtmCacheFailure::FAIL_REMOTE) {
138  fail_reason = HtmFailureFaultCause::MEMORY;
139  } else if (htm_rc == HtmCacheFailure::FAIL_OTHER) {
140  // these are likely loads that were issued out of order
141  // they are faulted here, but it's unlikely that these will
142  // ever reach the commit head.
143  fail_reason = HtmFailureFaultCause::OTHER;
144  } else {
145  panic("HTM error - unhandled return code from cache (%s)",
146  htmFailureToStr(htm_rc));
147  }
148 
149  inst->fault =
150  std::make_shared<GenericHtmFailureFault>(
151  inst->getHtmTransactionUid(),
152  fail_reason);
153 
154  DPRINTF(HtmCpu,
155  "load notification of HTM transaction failure "
156  "in cache - pc=%s - addr=0x%lx - "
157  "rc=%u - htmUid=%d\n",
158  inst->pcState(), pkt->getAddr(),
159  htmFailureToStr(htm_rc), pkt->getHtmTransactionUid());
160  }
161  }
162 
163  cpu->ppDataAccessComplete->notify(std::make_pair(inst, pkt));
164 
165  assert(!cpu->switchedOut());
166  if (!inst->isSquashed()) {
167  if (request->needWBToRegister()) {
168  // Only loads, store conditionals and atomics perform the writeback
169  // after receving the response from the memory
170  assert(inst->isLoad() || inst->isStoreConditional() ||
171  inst->isAtomic());
172 
173  // hardware transactional memory
174  if (pkt->htmTransactionFailedInCache()) {
177  }
178 
179  writeback(inst, request->mainPacket());
180  if (inst->isStore() || inst->isAtomic()) {
181  request->writebackDone();
182  completeStore(request->instruction()->sqIt);
183  }
184  } else if (inst->isStore()) {
185  // This is a regular store (i.e., not store conditionals and
186  // atomics), so it can complete without writing back
187  completeStore(request->instruction()->sqIt);
188  }
189  }
190 }
191 
192 LSQUnit::LSQUnit(uint32_t lqEntries, uint32_t sqEntries)
193  : lsqID(-1), storeQueue(sqEntries), loadQueue(lqEntries),
194  storesToWB(0),
195  htmStarts(0), htmStops(0),
197  cacheBlockMask(0), stalled(false),
198  isStoreBlocked(false), storeInFlight(false), stats(nullptr)
199 {
200 }
201 
202 void
203 LSQUnit::init(CPU *cpu_ptr, IEW *iew_ptr, const BaseO3CPUParams &params,
204  LSQ *lsq_ptr, unsigned id)
205 {
206  lsqID = id;
207 
208  cpu = cpu_ptr;
209  iewStage = iew_ptr;
210 
211  lsq = lsq_ptr;
212 
213  cpu->addStatGroup(csprintf("lsq%i", lsqID).c_str(), &stats);
214 
215  DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",lsqID);
216 
217  depCheckShift = params.LSQDepCheckShift;
218  checkLoads = params.LSQCheckLoads;
219  needsTSO = params.needsTSO;
220 
221  resetState();
222 }
223 
224 
225 void
227 {
228  storesToWB = 0;
229 
230  // hardware transactional memory
231  // nesting depth
232  htmStarts = htmStops = 0;
233 
235 
236  retryPkt = NULL;
237  memDepViolator = NULL;
238 
239  stalled = false;
240 
241  cacheBlockMask = ~(cpu->cacheLineSize() - 1);
242 }
243 
244 std::string
246 {
247  if (MaxThreads == 1) {
248  return iewStage->name() + ".lsq";
249  } else {
250  return iewStage->name() + ".lsq.thread" + std::to_string(lsqID);
251  }
252 }
253 
255  : statistics::Group(parent),
256  ADD_STAT(forwLoads, statistics::units::Count::get(),
257  "Number of loads that had data forwarded from stores"),
258  ADD_STAT(squashedLoads, statistics::units::Count::get(),
259  "Number of loads squashed"),
260  ADD_STAT(ignoredResponses, statistics::units::Count::get(),
261  "Number of memory responses ignored because the instruction is "
262  "squashed"),
263  ADD_STAT(memOrderViolation, statistics::units::Count::get(),
264  "Number of memory ordering violations"),
265  ADD_STAT(squashedStores, statistics::units::Count::get(),
266  "Number of stores squashed"),
267  ADD_STAT(rescheduledLoads, statistics::units::Count::get(),
268  "Number of loads that were rescheduled"),
269  ADD_STAT(blockedByCache, statistics::units::Count::get(),
270  "Number of times an access to memory failed due to the cache "
271  "being blocked"),
272  ADD_STAT(loadToUse, "Distribution of cycle latency between the "
273  "first time a load is issued and its completion")
274 {
275  loadToUse
276  .init(0, 299, 10)
278 }
279 
280 void
282 {
283  dcachePort = dcache_port;
284 }
285 
286 void
288 {
289  for (int i = 0; i < loadQueue.capacity(); ++i)
290  assert(!loadQueue[i].valid());
291 
292  assert(storesToWB == 0);
293  assert(!retryPkt);
294 }
295 
296 void
298 {
299  resetState();
300 }
301 
302 void
304 {
305  assert(inst->isMemRef());
306 
307  assert(inst->isLoad() || inst->isStore() || inst->isAtomic());
308 
309  if (inst->isLoad()) {
310  insertLoad(inst);
311  } else {
312  insertStore(inst);
313  }
314 
315  inst->setInLSQ();
316 }
317 
318 void
320 {
321  assert(!loadQueue.full());
322  assert(loadQueue.size() < loadQueue.capacity());
323 
324  DPRINTF(LSQUnit, "Inserting load PC %s, idx:%i [sn:%lli]\n",
325  load_inst->pcState(), loadQueue.tail(), load_inst->seqNum);
326 
327  /* Grow the queue. */
329 
330  load_inst->sqIt = storeQueue.end();
331 
332  assert(!loadQueue.back().valid());
333  loadQueue.back().set(load_inst);
334  load_inst->lqIdx = loadQueue.tail();
335  assert(load_inst->lqIdx > 0);
336  load_inst->lqIt = loadQueue.getIterator(load_inst->lqIdx);
337 
338  // hardware transactional memory
339  // transactional state and nesting depth must be tracked
340  // in the in-order part of the core.
341  if (load_inst->isHtmStart()) {
342  htmStarts++;
343  DPRINTF(HtmCpu, ">> htmStarts++ (%d) : htmStops (%d)\n",
345 
346  const int htm_depth = htmStarts - htmStops;
347  const auto& htm_cpt = cpu->tcBase(lsqID)->getHtmCheckpointPtr();
348  auto htm_uid = htm_cpt->getHtmUid();
349 
350  // for debugging purposes
351  if (!load_inst->inHtmTransactionalState()) {
352  htm_uid = htm_cpt->newHtmUid();
353  DPRINTF(HtmCpu, "generating new htmUid=%u\n", htm_uid);
354  if (htm_depth != 1) {
355  DPRINTF(HtmCpu,
356  "unusual HTM transactional depth (%d)"
357  " possibly caused by mispeculation - htmUid=%u\n",
358  htm_depth, htm_uid);
359  }
360  }
361  load_inst->setHtmTransactionalState(htm_uid, htm_depth);
362  }
363 
364  if (load_inst->isHtmStop()) {
365  htmStops++;
366  DPRINTF(HtmCpu, ">> htmStarts (%d) : htmStops++ (%d)\n",
368 
369  if (htmStops==1 && htmStarts==0) {
370  DPRINTF(HtmCpu,
371  "htmStops==1 && htmStarts==0. "
372  "This generally shouldn't happen "
373  "(unless due to misspeculation)\n");
374  }
375  }
376 }
377 
378 void
380 {
381  // Make sure it is not full before inserting an instruction.
382  assert(!storeQueue.full());
383  assert(storeQueue.size() < storeQueue.capacity());
384 
385  DPRINTF(LSQUnit, "Inserting store PC %s, idx:%i [sn:%lli]\n",
386  store_inst->pcState(), storeQueue.tail(), store_inst->seqNum);
388 
389  store_inst->sqIdx = storeQueue.tail();
390  store_inst->sqIt = storeQueue.getIterator(store_inst->sqIdx);
391 
392  store_inst->lqIdx = loadQueue.tail() + 1;
393  assert(store_inst->lqIdx > 0);
394  store_inst->lqIt = loadQueue.end();
395 
396  storeQueue.back().set(store_inst);
397 }
398 
401 {
402  DynInstPtr temp = memDepViolator;
403 
404  memDepViolator = NULL;
405 
406  return temp;
407 }
408 
409 unsigned
411 {
412  DPRINTF(LSQUnit, "LQ size: %d, #loads occupied: %d\n",
414  return loadQueue.capacity() - loadQueue.size();
415 }
416 
417 unsigned
419 {
420  DPRINTF(LSQUnit, "SQ size: %d, #stores occupied: %d\n",
422  return storeQueue.capacity() - storeQueue.size();
423 
424  }
425 
426 void
428 {
429  // Should only ever get invalidations in here
430  assert(pkt->isInvalidate());
431 
432  DPRINTF(LSQUnit, "Got snoop for address %#x\n", pkt->getAddr());
433 
434  for (int x = 0; x < cpu->numContexts(); x++) {
436  bool no_squash = cpu->thread[x]->noSquashFromTC;
437  cpu->thread[x]->noSquashFromTC = true;
439  cpu->thread[x]->noSquashFromTC = no_squash;
440  }
441 
442  if (loadQueue.empty())
443  return;
444 
445  auto iter = loadQueue.begin();
446 
447  Addr invalidate_addr = pkt->getAddr() & cacheBlockMask;
448 
449  DynInstPtr ld_inst = iter->instruction();
450  assert(ld_inst);
451  LSQRequest *request = iter->request();
452 
453  // Check that this snoop didn't just invalidate our lock flag
454  if (ld_inst->effAddrValid() &&
455  request->isCacheBlockHit(invalidate_addr, cacheBlockMask)
456  && ld_inst->memReqFlags & Request::LLSC) {
457  ld_inst->tcBase()->getIsaPtr()->handleLockedSnoopHit(ld_inst.get());
458  }
459 
460  bool force_squash = false;
461 
462  while (++iter != loadQueue.end()) {
463  ld_inst = iter->instruction();
464  assert(ld_inst);
465  request = iter->request();
466  if (!ld_inst->effAddrValid() || ld_inst->strictlyOrdered())
467  continue;
468 
469  DPRINTF(LSQUnit, "-- inst [sn:%lli] to pktAddr:%#x\n",
470  ld_inst->seqNum, invalidate_addr);
471 
472  if (force_squash ||
473  request->isCacheBlockHit(invalidate_addr, cacheBlockMask)) {
474  if (needsTSO) {
475  // If we have a TSO system, as all loads must be ordered with
476  // all other loads, this load as well as *all* subsequent loads
477  // need to be squashed to prevent possible load reordering.
478  force_squash = true;
479  }
480  if (ld_inst->possibleLoadViolation() || force_squash) {
481  DPRINTF(LSQUnit, "Conflicting load at addr %#x [sn:%lli]\n",
482  pkt->getAddr(), ld_inst->seqNum);
483 
484  // Mark the load for re-execution
485  ld_inst->fault = std::make_shared<ReExec>();
486  request->setStateToFault();
487  } else {
488  DPRINTF(LSQUnit, "HitExternal Snoop for addr %#x [sn:%lli]\n",
489  pkt->getAddr(), ld_inst->seqNum);
490 
491  // Make sure that we don't lose a snoop hitting a LOCKED
492  // address since the LOCK* flags don't get updated until
493  // commit.
494  if (ld_inst->memReqFlags & Request::LLSC) {
495  ld_inst->tcBase()->getIsaPtr()->
496  handleLockedSnoopHit(ld_inst.get());
497  }
498 
499  // If a older load checks this and it's true
500  // then we might have missed the snoop
501  // in which case we need to invalidate to be sure
502  ld_inst->hitExternalSnoop(true);
503  }
504  }
505  }
506  return;
507 }
508 
509 Fault
510 LSQUnit::checkViolations(typename LoadQueue::iterator& loadIt,
511  const DynInstPtr& inst)
512 {
513  Addr inst_eff_addr1 = inst->effAddr >> depCheckShift;
514  Addr inst_eff_addr2 = (inst->effAddr + inst->effSize - 1) >> depCheckShift;
515 
521  while (loadIt != loadQueue.end()) {
522  DynInstPtr ld_inst = loadIt->instruction();
523  if (!ld_inst->effAddrValid() || ld_inst->strictlyOrdered()) {
524  ++loadIt;
525  continue;
526  }
527 
528  Addr ld_eff_addr1 = ld_inst->effAddr >> depCheckShift;
529  Addr ld_eff_addr2 =
530  (ld_inst->effAddr + ld_inst->effSize - 1) >> depCheckShift;
531 
532  if (inst_eff_addr2 >= ld_eff_addr1 && inst_eff_addr1 <= ld_eff_addr2) {
533  if (inst->isLoad()) {
534  // If this load is to the same block as an external snoop
535  // invalidate that we've observed then the load needs to be
536  // squashed as it could have newer data
537  if (ld_inst->hitExternalSnoop()) {
538  if (!memDepViolator ||
539  ld_inst->seqNum < memDepViolator->seqNum) {
540  DPRINTF(LSQUnit, "Detected fault with inst [sn:%lli] "
541  "and [sn:%lli] at address %#x\n",
542  inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
543  memDepViolator = ld_inst;
544 
546 
547  return std::make_shared<GenericISA::M5PanicFault>(
548  "Detected fault with inst [sn:%lli] and "
549  "[sn:%lli] at address %#x\n",
550  inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
551  }
552  }
553 
554  // Otherwise, mark the load has a possible load violation and
555  // if we see a snoop before it's commited, we need to squash
556  ld_inst->possibleLoadViolation(true);
557  DPRINTF(LSQUnit, "Found possible load violation at addr: %#x"
558  " between instructions [sn:%lli] and [sn:%lli]\n",
559  inst_eff_addr1, inst->seqNum, ld_inst->seqNum);
560  } else {
561  // A load/store incorrectly passed this store.
562  // Check if we already have a violator, or if it's newer
563  // squash and refetch.
564  if (memDepViolator && ld_inst->seqNum > memDepViolator->seqNum)
565  break;
566 
567  DPRINTF(LSQUnit, "Detected fault with inst [sn:%lli] and "
568  "[sn:%lli] at address %#x\n",
569  inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
570  memDepViolator = ld_inst;
571 
573 
574  return std::make_shared<GenericISA::M5PanicFault>(
575  "Detected fault with "
576  "inst [sn:%lli] and [sn:%lli] at address %#x\n",
577  inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
578  }
579  }
580 
581  ++loadIt;
582  }
583  return NoFault;
584 }
585 
586 
587 
588 
589 Fault
591 {
592  // Execute a specific load.
593  Fault load_fault = NoFault;
594 
595  DPRINTF(LSQUnit, "Executing load PC %s, [sn:%lli]\n",
596  inst->pcState(), inst->seqNum);
597 
598  assert(!inst->isSquashed());
599 
600  load_fault = inst->initiateAcc();
601 
602  if (load_fault == NoFault && !inst->readMemAccPredicate()) {
603  assert(inst->readPredicate());
604  inst->setExecuted();
605  inst->completeAcc(nullptr);
606  iewStage->instToCommit(inst);
608  return NoFault;
609  }
610 
611  if (inst->isTranslationDelayed() && load_fault == NoFault)
612  return load_fault;
613 
614  if (load_fault != NoFault && inst->translationCompleted() &&
615  inst->savedRequest->isPartialFault()
616  && !inst->savedRequest->isComplete()) {
617  assert(inst->savedRequest->isSplit());
618  // If we have a partial fault where the mem access is not complete yet
619  // then the cache must have been blocked. This load will be re-executed
620  // when the cache gets unblocked. We will handle the fault when the
621  // mem access is complete.
622  return NoFault;
623  }
624 
625  // If the instruction faulted or predicated false, then we need to send it
626  // along to commit without the instruction completing.
627  if (load_fault != NoFault || !inst->readPredicate()) {
628  // Send this instruction to commit, also make sure iew stage
629  // realizes there is activity. Mark it as executed unless it
630  // is a strictly ordered load that needs to hit the head of
631  // commit.
632  if (!inst->readPredicate())
633  inst->forwardOldRegs();
634  DPRINTF(LSQUnit, "Load [sn:%lli] not executed from %s\n",
635  inst->seqNum,
636  (load_fault != NoFault ? "fault" : "predication"));
637  if (!(inst->hasRequest() && inst->strictlyOrdered()) ||
638  inst->isAtCommit()) {
639  inst->setExecuted();
640  }
641  iewStage->instToCommit(inst);
643  } else {
644  if (inst->effAddrValid()) {
645  auto it = inst->lqIt;
646  ++it;
647 
648  if (checkLoads)
649  return checkViolations(it, inst);
650  }
651  }
652 
653  return load_fault;
654 }
655 
656 Fault
658 {
659  // Make sure that a store exists.
660  assert(storeQueue.size() != 0);
661 
662  ssize_t store_idx = store_inst->sqIdx;
663 
664  DPRINTF(LSQUnit, "Executing store PC %s [sn:%lli]\n",
665  store_inst->pcState(), store_inst->seqNum);
666 
667  assert(!store_inst->isSquashed());
668 
669  // Check the recently completed loads to see if any match this store's
670  // address. If so, then we have a memory ordering violation.
671  typename LoadQueue::iterator loadIt = store_inst->lqIt;
672 
673  Fault store_fault = store_inst->initiateAcc();
674 
675  if (store_inst->isTranslationDelayed() &&
676  store_fault == NoFault)
677  return store_fault;
678 
679  if (!store_inst->readPredicate()) {
680  DPRINTF(LSQUnit, "Store [sn:%lli] not executed from predication\n",
681  store_inst->seqNum);
682  store_inst->forwardOldRegs();
683  return store_fault;
684  }
685 
686  if (storeQueue[store_idx].size() == 0) {
687  DPRINTF(LSQUnit,"Fault on Store PC %s, [sn:%lli], Size = 0\n",
688  store_inst->pcState(), store_inst->seqNum);
689 
690  if (store_inst->isAtomic()) {
691  // If the instruction faulted, then we need to send it along
692  // to commit without the instruction completing.
693  if (!(store_inst->hasRequest() && store_inst->strictlyOrdered()) ||
694  store_inst->isAtCommit()) {
695  store_inst->setExecuted();
696  }
697  iewStage->instToCommit(store_inst);
699  }
700 
701  return store_fault;
702  }
703 
704  assert(store_fault == NoFault);
705 
706  if (store_inst->isStoreConditional() || store_inst->isAtomic()) {
707  // Store conditionals and Atomics need to set themselves as able to
708  // writeback if we haven't had a fault by here.
709  storeQueue[store_idx].canWB() = true;
710 
711  ++storesToWB;
712  }
713 
714  return checkViolations(loadIt, store_inst);
715 
716 }
717 
718 void
720 {
721  assert(loadQueue.front().valid());
722 
723  DynInstPtr inst = loadQueue.front().instruction();
724 
725  DPRINTF(LSQUnit, "Committing head load instruction, PC %s\n",
726  inst->pcState());
727 
728  // Update histogram with memory latency from load
729  // Only take latency from load demand that where issued and did not fault
730  if (!inst->isInstPrefetch() && !inst->isDataPrefetch()
731  && inst->firstIssue != -1
732  && inst->lastWakeDependents != -1) {
734  inst->lastWakeDependents - inst->firstIssue));
735  }
736 
737  loadQueue.front().clear();
739 }
740 
741 void
743 {
744  assert(loadQueue.size() == 0 || loadQueue.front().valid());
745 
746  while (loadQueue.size() != 0 && loadQueue.front().instruction()->seqNum
747  <= youngest_inst) {
748  commitLoad();
749  }
750 }
751 
752 void
754 {
755  assert(storeQueue.size() == 0 || storeQueue.front().valid());
756 
757  /* Forward iterate the store queue (age order). */
758  for (auto& x : storeQueue) {
759  assert(x.valid());
760  // Mark any stores that are now committed and have not yet
761  // been marked as able to write back.
762  if (!x.canWB()) {
763  if (x.instruction()->seqNum > youngest_inst) {
764  break;
765  }
766  DPRINTF(LSQUnit, "Marking store as able to write back, PC "
767  "%s [sn:%lli]\n",
768  x.instruction()->pcState(),
769  x.instruction()->seqNum);
770 
771  x.canWB() = true;
772 
773  ++storesToWB;
774  }
775  }
776 }
777 
778 void
780 {
781  assert(isStoreBlocked);
782  storeWBIt->request()->sendPacketToCache();
783  if (storeWBIt->request()->isSent()){
784  storePostSend();
785  }
786 }
787 
788 void
790 {
791  if (isStoreBlocked) {
792  DPRINTF(LSQUnit, "Writing back blocked store\n");
794  }
795 
796  while (storesToWB > 0 &&
797  storeWBIt.dereferenceable() &&
798  storeWBIt->valid() &&
799  storeWBIt->canWB() &&
800  ((!needsTSO) || (!storeInFlight)) &&
801  lsq->cachePortAvailable(false)) {
802 
803  if (isStoreBlocked) {
804  DPRINTF(LSQUnit, "Unable to write back any more stores, cache"
805  " is blocked!\n");
806  break;
807  }
808 
809  // Store didn't write any data so no need to write it back to
810  // memory.
811  if (storeWBIt->size() == 0) {
812  /* It is important that the preincrement happens at (or before)
813  * the call, as the the code of completeStore checks
814  * storeWBIt. */
816  continue;
817  }
818 
819  if (storeWBIt->instruction()->isDataPrefetch()) {
820  storeWBIt++;
821  continue;
822  }
823 
824  assert(storeWBIt->hasRequest());
825  assert(!storeWBIt->committed());
826 
827  DynInstPtr inst = storeWBIt->instruction();
828  LSQRequest* request = storeWBIt->request();
829 
830  // Process store conditionals or store release after all previous
831  // stores are completed
832  if ((request->mainReq()->isLLSC() ||
833  request->mainReq()->isRelease()) &&
834  (storeWBIt.idx() != storeQueue.head())) {
835  DPRINTF(LSQUnit, "Store idx:%i PC:%s to Addr:%#x "
836  "[sn:%lli] is %s%s and not head of the queue\n",
837  storeWBIt.idx(), inst->pcState(),
838  request->mainReq()->getPaddr(), inst->seqNum,
839  request->mainReq()->isLLSC() ? "SC" : "",
840  request->mainReq()->isRelease() ? "/Release" : "");
841  break;
842  }
843 
844  storeWBIt->committed() = true;
845 
846  assert(!inst->memData);
847  inst->memData = new uint8_t[request->_size];
848 
849  if (storeWBIt->isAllZeros())
850  memset(inst->memData, 0, request->_size);
851  else
852  memcpy(inst->memData, storeWBIt->data(), request->_size);
853 
854  request->buildPackets();
855 
856  DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%s "
857  "to Addr:%#x, data:%#x [sn:%lli]\n",
858  storeWBIt.idx(), inst->pcState(),
859  request->mainReq()->getPaddr(), (int)*(inst->memData),
860  inst->seqNum);
861 
862  // @todo: Remove this SC hack once the memory system handles it.
863  if (inst->isStoreConditional()) {
864  // Disable recording the result temporarily. Writing to
865  // misc regs normally updates the result, but this is not
866  // the desired behavior when handling store conditionals.
867  inst->recordResult(false);
868  bool success = inst->tcBase()->getIsaPtr()->handleLockedWrite(
869  inst.get(), request->mainReq(), cacheBlockMask);
870  inst->recordResult(true);
871  request->packetSent();
872 
873  if (!success) {
874  request->complete();
875  // Instantly complete this store.
876  DPRINTF(LSQUnit, "Store conditional [sn:%lli] failed. "
877  "Instantly completing it.\n",
878  inst->seqNum);
879  PacketPtr new_pkt = new Packet(*request->packet());
880  WritebackEvent *wb = new WritebackEvent(inst,
881  new_pkt, this);
882  cpu->schedule(wb, curTick() + 1);
884  if (!storeQueue.empty())
885  storeWBIt++;
886  else
888  continue;
889  }
890  }
891 
892  if (request->mainReq()->isLocalAccess()) {
893  assert(!inst->isStoreConditional());
894  assert(!inst->inHtmTransactionalState());
895  gem5::ThreadContext *thread = cpu->tcBase(lsqID);
896  PacketPtr main_pkt = new Packet(request->mainReq(),
898  main_pkt->dataStatic(inst->memData);
899  request->mainReq()->localAccessor(thread, main_pkt);
900  delete main_pkt;
902  storeWBIt++;
903  continue;
904  }
905  /* Send to cache */
906  request->sendPacketToCache();
907 
908  /* If successful, do the post send */
909  if (request->isSent()) {
910  storePostSend();
911  } else {
912  DPRINTF(LSQUnit, "D-Cache became blocked when writing [sn:%lli], "
913  "will retry later\n",
914  inst->seqNum);
915  }
916  }
917  assert(storesToWB >= 0);
918 }
919 
920 void
921 LSQUnit::squash(const InstSeqNum &squashed_num)
922 {
923  DPRINTF(LSQUnit, "Squashing until [sn:%lli]!"
924  "(Loads:%i Stores:%i)\n", squashed_num, loadQueue.size(),
925  storeQueue.size());
926 
927  while (loadQueue.size() != 0 &&
928  loadQueue.back().instruction()->seqNum > squashed_num) {
929  DPRINTF(LSQUnit,"Load Instruction PC %s squashed, "
930  "[sn:%lli]\n",
931  loadQueue.back().instruction()->pcState(),
932  loadQueue.back().instruction()->seqNum);
933 
934  if (isStalled() && loadQueue.tail() == stallingLoadIdx) {
935  stalled = false;
936  stallingStoreIsn = 0;
937  stallingLoadIdx = 0;
938  }
939 
940  // hardware transactional memory
941  // Squashing instructions can alter the transaction nesting depth
942  // and must be corrected before fetching resumes.
943  if (loadQueue.back().instruction()->isHtmStart())
944  {
945  htmStarts = (--htmStarts < 0) ? 0 : htmStarts;
946  DPRINTF(HtmCpu, ">> htmStarts-- (%d) : htmStops (%d)\n",
948  }
949  if (loadQueue.back().instruction()->isHtmStop())
950  {
951  htmStops = (--htmStops < 0) ? 0 : htmStops;
952  DPRINTF(HtmCpu, ">> htmStarts (%d) : htmStops-- (%d)\n",
954  }
955  // Clear the smart pointer to make sure it is decremented.
956  loadQueue.back().instruction()->setSquashed();
957  loadQueue.back().clear();
958 
961  }
962 
963  // hardware transactional memory
964  // scan load queue (from oldest to youngest) for most recent valid htmUid
965  auto scan_it = loadQueue.begin();
966  uint64_t in_flight_uid = 0;
967  while (scan_it != loadQueue.end()) {
968  if (scan_it->instruction()->isHtmStart() &&
969  !scan_it->instruction()->isSquashed()) {
970  in_flight_uid = scan_it->instruction()->getHtmTransactionUid();
971  DPRINTF(HtmCpu, "loadQueue[%d]: found valid HtmStart htmUid=%u\n",
972  scan_it._idx, in_flight_uid);
973  }
974  scan_it++;
975  }
976  // If there's a HtmStart in the pipeline then use its htmUid,
977  // otherwise use the most recently committed uid
978  const auto& htm_cpt = cpu->tcBase(lsqID)->getHtmCheckpointPtr();
979  if (htm_cpt) {
980  const uint64_t old_local_htm_uid = htm_cpt->getHtmUid();
981  uint64_t new_local_htm_uid;
982  if (in_flight_uid > 0)
983  new_local_htm_uid = in_flight_uid;
984  else
985  new_local_htm_uid = lastRetiredHtmUid;
986 
987  if (old_local_htm_uid != new_local_htm_uid) {
988  DPRINTF(HtmCpu, "flush: lastRetiredHtmUid=%u\n",
990  DPRINTF(HtmCpu, "flush: resetting localHtmUid=%u\n",
991  new_local_htm_uid);
992 
993  htm_cpt->setHtmUid(new_local_htm_uid);
994  }
995  }
996 
997  if (memDepViolator && squashed_num < memDepViolator->seqNum) {
998  memDepViolator = NULL;
999  }
1000 
1001  while (storeQueue.size() != 0 &&
1002  storeQueue.back().instruction()->seqNum > squashed_num) {
1003  // Instructions marked as can WB are already committed.
1004  if (storeQueue.back().canWB()) {
1005  break;
1006  }
1007 
1008  DPRINTF(LSQUnit,"Store Instruction PC %s squashed, "
1009  "idx:%i [sn:%lli]\n",
1010  storeQueue.back().instruction()->pcState(),
1011  storeQueue.tail(), storeQueue.back().instruction()->seqNum);
1012 
1013  // I don't think this can happen. It should have been cleared
1014  // by the stalling load.
1015  if (isStalled() &&
1016  storeQueue.back().instruction()->seqNum == stallingStoreIsn) {
1017  panic("Is stalled should have been cleared by stalling load!\n");
1018  stalled = false;
1019  stallingStoreIsn = 0;
1020  }
1021 
1022  // Clear the smart pointer to make sure it is decremented.
1023  storeQueue.back().instruction()->setSquashed();
1024 
1025  // Must delete request now that it wasn't handed off to
1026  // memory. This is quite ugly. @todo: Figure out the proper
1027  // place to really handle request deletes.
1028  storeQueue.back().clear();
1029 
1030  storeQueue.pop_back();
1032  }
1033 }
1034 
1035 uint64_t
1037 {
1038  const auto& htm_cpt = cpu->tcBase(lsqID)->getHtmCheckpointPtr();
1039  return htm_cpt->getHtmUid();
1040 }
1041 
1042 void
1044 {
1045  if (isStalled() &&
1046  storeWBIt->instruction()->seqNum == stallingStoreIsn) {
1047  DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
1048  "load idx:%li\n",
1050  stalled = false;
1051  stallingStoreIsn = 0;
1053  }
1054 
1055  if (!storeWBIt->instruction()->isStoreConditional()) {
1056  // The store is basically completed at this time. This
1057  // only works so long as the checker doesn't try to
1058  // verify the value in memory for stores.
1059  storeWBIt->instruction()->setCompleted();
1060 
1061  if (cpu->checker) {
1062  cpu->checker->verify(storeWBIt->instruction());
1063  }
1064  }
1065 
1066  if (needsTSO) {
1067  storeInFlight = true;
1068  }
1069 
1070  storeWBIt++;
1071 }
1072 
1073 void
1075 {
1076  iewStage->wakeCPU();
1077 
1078  // Squashed instructions do not need to complete their access.
1079  if (inst->isSquashed()) {
1080  assert (!inst->isStore() || inst->isStoreConditional());
1082  return;
1083  }
1084 
1085  if (!inst->isExecuted()) {
1086  inst->setExecuted();
1087 
1088  if (inst->fault == NoFault) {
1089  // Complete access to copy data to proper place.
1090  inst->completeAcc(pkt);
1091  } else {
1092  // If the instruction has an outstanding fault, we cannot complete
1093  // the access as this discards the current fault.
1094 
1095  // If we have an outstanding fault, the fault should only be of
1096  // type ReExec or - in case of a SplitRequest - a partial
1097  // translation fault
1098 
1099  // Unless it's a hardware transactional memory fault
1100  auto htm_fault = std::dynamic_pointer_cast<
1101  GenericHtmFailureFault>(inst->fault);
1102 
1103  if (!htm_fault) {
1104  assert(dynamic_cast<ReExec*>(inst->fault.get()) != nullptr ||
1105  inst->savedRequest->isPartialFault());
1106 
1107  } else if (!pkt->htmTransactionFailedInCache()) {
1108  // Situation in which the instruction has a hardware
1109  // transactional memory fault but not the packet itself. This
1110  // can occur with ldp_uop microops since access is spread over
1111  // multiple packets.
1112  DPRINTF(HtmCpu,
1113  "%s writeback with HTM failure fault, "
1114  "however, completing packet is not aware of "
1115  "transaction failure. cause=%s htmUid=%u\n",
1116  inst->staticInst->getName(),
1117  htmFailureToStr(htm_fault->getHtmFailureFaultCause()),
1118  htm_fault->getHtmUid());
1119  }
1120 
1121  DPRINTF(LSQUnit, "Not completing instruction [sn:%lli] access "
1122  "due to pending fault.\n", inst->seqNum);
1123  }
1124  }
1125 
1126  // Need to insert instruction into queue to commit
1127  iewStage->instToCommit(inst);
1128 
1130 
1131  // see if this load changed the PC
1133 }
1134 
1135 void
1136 LSQUnit::completeStore(typename StoreQueue::iterator store_idx)
1137 {
1138  assert(store_idx->valid());
1139  store_idx->completed() = true;
1140  --storesToWB;
1141  // A bit conservative because a store completion may not free up entries,
1142  // but hopefully avoids two store completions in one cycle from making
1143  // the CPU tick twice.
1144  cpu->wakeCPU();
1146 
1147  /* We 'need' a copy here because we may clear the entry from the
1148  * store queue. */
1149  DynInstPtr store_inst = store_idx->instruction();
1150  if (store_idx == storeQueue.begin()) {
1151  do {
1152  storeQueue.front().clear();
1154  } while (storeQueue.front().completed() &&
1155  !storeQueue.empty());
1156 
1157  iewStage->updateLSQNextCycle = true;
1158  }
1159 
1160  DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head "
1161  "idx:%i\n",
1162  store_inst->seqNum, store_idx.idx() - 1, storeQueue.head() - 1);
1163 
1164 #if TRACING_ON
1165  if (debug::O3PipeView) {
1166  store_inst->storeTick =
1167  curTick() - store_inst->fetchTick;
1168  }
1169 #endif
1170 
1171  if (isStalled() &&
1172  store_inst->seqNum == stallingStoreIsn) {
1173  DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
1174  "load idx:%li\n",
1176  stalled = false;
1177  stallingStoreIsn = 0;
1179  }
1180 
1181  store_inst->setCompleted();
1182 
1183  if (needsTSO) {
1184  storeInFlight = false;
1185  }
1186 
1187  // Tell the checker we've completed this instruction. Some stores
1188  // may get reported twice to the checker, but the checker can
1189  // handle that case.
1190  // Store conditionals cannot be sent to the checker yet, they have
1191  // to update the misc registers first which should take place
1192  // when they commit
1193  if (cpu->checker && !store_inst->isStoreConditional()) {
1194  cpu->checker->verify(store_inst);
1195  }
1196 }
1197 
1198 bool
1199 LSQUnit::trySendPacket(bool isLoad, PacketPtr data_pkt)
1200 {
1201  bool ret = true;
1202  bool cache_got_blocked = false;
1203 
1204  LSQRequest *request = dynamic_cast<LSQRequest*>(data_pkt->senderState);
1205 
1206  if (!lsq->cacheBlocked() &&
1207  lsq->cachePortAvailable(isLoad)) {
1208  if (!dcachePort->sendTimingReq(data_pkt)) {
1209  ret = false;
1210  cache_got_blocked = true;
1211  }
1212  } else {
1213  ret = false;
1214  }
1215 
1216  if (ret) {
1217  if (!isLoad) {
1218  isStoreBlocked = false;
1219  }
1220  lsq->cachePortBusy(isLoad);
1221  request->packetSent();
1222  } else {
1223  if (cache_got_blocked) {
1224  lsq->cacheBlocked(true);
1226  }
1227  if (!isLoad) {
1228  assert(request == storeWBIt->request());
1229  isStoreBlocked = true;
1230  }
1231  request->packetNotSent();
1232  }
1233  DPRINTF(LSQUnit, "Memory request (pkt: %s) from inst [sn:%llu] was"
1234  " %ssent (cache is blocked: %d, cache_got_blocked: %d)\n",
1235  data_pkt->print(), request->instruction()->seqNum,
1236  ret ? "": "not ", lsq->cacheBlocked(), cache_got_blocked);
1237  return ret;
1238 }
1239 
1240 void
1242 {
1243  DPRINTF(LSQUnit, "Unit %p marking stale translations %d %d\n", this,
1244  storeQueue.size(), loadQueue.size());
1245  for (auto& entry : storeQueue) {
1246  if (entry.valid() && entry.hasRequest())
1247  entry.request()->markAsStaleTranslation();
1248  }
1249  for (auto& entry : loadQueue) {
1250  if (entry.valid() && entry.hasRequest())
1251  entry.request()->markAsStaleTranslation();
1252  }
1253 }
1254 
1255 bool
1257 {
1258  DPRINTF(LSQUnit, "Unit %p checking stale translations\n", this);
1259  for (auto& entry : storeQueue) {
1260  if (entry.valid() && entry.hasRequest()
1261  && entry.request()->hasStaleTranslation())
1262  return true;
1263  }
1264  for (auto& entry : loadQueue) {
1265  if (entry.valid() && entry.hasRequest()
1266  && entry.request()->hasStaleTranslation())
1267  return true;
1268  }
1269  DPRINTF(LSQUnit, "Unit %p found no stale translations\n", this);
1270  return false;
1271 }
1272 
1273 void
1275 {
1276  if (isStoreBlocked) {
1277  DPRINTF(LSQUnit, "Receiving retry: blocked store\n");
1279  }
1280 }
1281 
1282 void
1284 {
1285  cprintf("Load store queue: Dumping instructions.\n");
1286  cprintf("Load queue size: %i\n", loadQueue.size());
1287  cprintf("Load queue: ");
1288 
1289  for (const auto& e: loadQueue) {
1290  const DynInstPtr &inst(e.instruction());
1291  cprintf("%s.[sn:%llu] ", inst->pcState(), inst->seqNum);
1292  }
1293  cprintf("\n");
1294 
1295  cprintf("Store queue size: %i\n", storeQueue.size());
1296  cprintf("Store queue: ");
1297 
1298  for (const auto& e: storeQueue) {
1299  const DynInstPtr &inst(e.instruction());
1300  cprintf("%s.[sn:%llu] ", inst->pcState(), inst->seqNum);
1301  }
1302 
1303  cprintf("\n");
1304 }
1305 
1306 void LSQUnit::schedule(Event& ev, Tick when) { cpu->schedule(ev, when); }
1307 
1309 
1310 unsigned int
1312 {
1313  return cpu->cacheLineSize();
1314 }
1315 
1316 Fault
1317 LSQUnit::read(LSQRequest *request, ssize_t load_idx)
1318 {
1319  LQEntry& load_entry = loadQueue[load_idx];
1320  const DynInstPtr& load_inst = load_entry.instruction();
1321 
1322  load_entry.setRequest(request);
1323  assert(load_inst);
1324 
1325  assert(!load_inst->isExecuted());
1326 
1327  // Make sure this isn't a strictly ordered load
1328  // A bit of a hackish way to get strictly ordered accesses to work
1329  // only if they're at the head of the LSQ and are ready to commit
1330  // (at the head of the ROB too).
1331 
1332  if (request->mainReq()->isStrictlyOrdered() &&
1333  (load_idx != loadQueue.head() || !load_inst->isAtCommit())) {
1334  // Tell IQ/mem dep unit that this instruction will need to be
1335  // rescheduled eventually
1336  iewStage->rescheduleMemInst(load_inst);
1337  load_inst->clearIssued();
1338  load_inst->effAddrValid(false);
1340  DPRINTF(LSQUnit, "Strictly ordered load [sn:%lli] PC %s\n",
1341  load_inst->seqNum, load_inst->pcState());
1342 
1343  // Must delete request now that it wasn't handed off to
1344  // memory. This is quite ugly. @todo: Figure out the proper
1345  // place to really handle request deletes.
1346  load_entry.setRequest(nullptr);
1347  request->discard();
1348  return std::make_shared<GenericISA::M5PanicFault>(
1349  "Strictly ordered load [sn:%llx] PC %s\n",
1350  load_inst->seqNum, load_inst->pcState());
1351  }
1352 
1353  DPRINTF(LSQUnit, "Read called, load idx: %i, store idx: %i, "
1354  "storeHead: %i addr: %#x%s\n",
1355  load_idx - 1, load_inst->sqIt._idx, storeQueue.head() - 1,
1356  request->mainReq()->getPaddr(), request->isSplit() ? " split" :
1357  "");
1358 
1359  if (request->mainReq()->isLLSC()) {
1360  // Disable recording the result temporarily. Writing to misc
1361  // regs normally updates the result, but this is not the
1362  // desired behavior when handling store conditionals.
1363  load_inst->recordResult(false);
1364  load_inst->tcBase()->getIsaPtr()->handleLockedRead(load_inst.get(),
1365  request->mainReq());
1366  load_inst->recordResult(true);
1367  }
1368 
1369  if (request->mainReq()->isLocalAccess()) {
1370  assert(!load_inst->memData);
1371  load_inst->memData = new uint8_t[MaxDataBytes];
1372 
1373  gem5::ThreadContext *thread = cpu->tcBase(lsqID);
1374  PacketPtr main_pkt = new Packet(request->mainReq(), MemCmd::ReadReq);
1375 
1376  main_pkt->dataStatic(load_inst->memData);
1377 
1378  Cycles delay = request->mainReq()->localAccessor(thread, main_pkt);
1379 
1380  WritebackEvent *wb = new WritebackEvent(load_inst, main_pkt, this);
1381  cpu->schedule(wb, cpu->clockEdge(delay));
1382  return NoFault;
1383  }
1384 
1385  // Check the SQ for any previous stores that might lead to forwarding
1386  auto store_it = load_inst->sqIt;
1387  assert (store_it >= storeWBIt);
1388  // End once we've reached the top of the LSQ
1389  while (store_it != storeWBIt && !load_inst->isDataPrefetch()) {
1390  // Move the index to one younger
1391  store_it--;
1392  assert(store_it->valid());
1393  assert(store_it->instruction()->seqNum < load_inst->seqNum);
1394  int store_size = store_it->size();
1395 
1396  // Cache maintenance instructions go down via the store
1397  // path but they carry no data and they shouldn't be
1398  // considered for forwarding
1399  if (store_size != 0 && !store_it->instruction()->strictlyOrdered() &&
1400  !(store_it->request()->mainReq() &&
1401  store_it->request()->mainReq()->isCacheMaintenance())) {
1402  assert(store_it->instruction()->effAddrValid());
1403 
1404  // Check if the store data is within the lower and upper bounds of
1405  // addresses that the request needs.
1406  auto req_s = request->mainReq()->getVaddr();
1407  auto req_e = req_s + request->mainReq()->getSize();
1408  auto st_s = store_it->instruction()->effAddr;
1409  auto st_e = st_s + store_size;
1410 
1411  bool store_has_lower_limit = req_s >= st_s;
1412  bool store_has_upper_limit = req_e <= st_e;
1413  bool lower_load_has_store_part = req_s < st_e;
1414  bool upper_load_has_store_part = req_e > st_s;
1415 
1417 
1418  // If the store entry is not atomic (atomic does not have valid
1419  // data), the store has all of the data needed, and
1420  // the load is not LLSC, then
1421  // we can forward data from the store to the load
1422  if (!store_it->instruction()->isAtomic() &&
1423  store_has_lower_limit && store_has_upper_limit &&
1424  !request->mainReq()->isLLSC()) {
1425 
1426  const auto& store_req = store_it->request()->mainReq();
1427  coverage = store_req->isMasked() ?
1430  } else if (
1431  // This is the partial store-load forwarding case where a store
1432  // has only part of the load's data and the load isn't LLSC
1433  (!request->mainReq()->isLLSC() &&
1434  ((store_has_lower_limit && lower_load_has_store_part) ||
1435  (store_has_upper_limit && upper_load_has_store_part) ||
1436  (lower_load_has_store_part && upper_load_has_store_part))) ||
1437  // The load is LLSC, and the store has all or part of the
1438  // load's data
1439  (request->mainReq()->isLLSC() &&
1440  ((store_has_lower_limit || upper_load_has_store_part) &&
1441  (store_has_upper_limit || lower_load_has_store_part))) ||
1442  // The store entry is atomic and has all or part of the load's
1443  // data
1444  (store_it->instruction()->isAtomic() &&
1445  ((store_has_lower_limit || upper_load_has_store_part) &&
1446  (store_has_upper_limit || lower_load_has_store_part)))) {
1447 
1449  }
1450 
1451  if (coverage == AddrRangeCoverage::FullAddrRangeCoverage) {
1452  // Get shift amount for offset into the store's data.
1453  int shift_amt = request->mainReq()->getVaddr() -
1454  store_it->instruction()->effAddr;
1455 
1456  // Allocate memory if this is the first time a load is issued.
1457  if (!load_inst->memData) {
1458  load_inst->memData =
1459  new uint8_t[request->mainReq()->getSize()];
1460  }
1461  if (store_it->isAllZeros())
1462  memset(load_inst->memData, 0,
1463  request->mainReq()->getSize());
1464  else
1465  memcpy(load_inst->memData,
1466  store_it->data() + shift_amt,
1467  request->mainReq()->getSize());
1468 
1469  DPRINTF(LSQUnit, "Forwarding from store idx %i to load to "
1470  "addr %#x\n", store_it._idx,
1471  request->mainReq()->getVaddr());
1472 
1473  PacketPtr data_pkt = new Packet(request->mainReq(),
1474  MemCmd::ReadReq);
1475  data_pkt->dataStatic(load_inst->memData);
1476 
1477  // hardware transactional memory
1478  // Store to load forwarding within a transaction
1479  // This should be okay because the store will be sent to
1480  // the memory subsystem and subsequently get added to the
1481  // write set of the transaction. The write set has a stronger
1482  // property than the read set, so the load doesn't necessarily
1483  // have to be there.
1484  assert(!request->mainReq()->isHTMCmd());
1485  if (load_inst->inHtmTransactionalState()) {
1486  assert (!storeQueue[store_it._idx].completed());
1487  assert (
1488  storeQueue[store_it._idx].instruction()->
1489  inHtmTransactionalState());
1490  assert (
1491  load_inst->getHtmTransactionUid() ==
1492  storeQueue[store_it._idx].instruction()->
1493  getHtmTransactionUid());
1494  data_pkt->setHtmTransactional(
1495  load_inst->getHtmTransactionUid());
1496  DPRINTF(HtmCpu, "HTM LD (ST2LDF) "
1497  "pc=0x%lx - vaddr=0x%lx - "
1498  "paddr=0x%lx - htmUid=%u\n",
1499  load_inst->pcState().instAddr(),
1500  data_pkt->req->hasVaddr() ?
1501  data_pkt->req->getVaddr() : 0lu,
1502  data_pkt->getAddr(),
1503  load_inst->getHtmTransactionUid());
1504  }
1505 
1506  if (request->isAnyOutstandingRequest()) {
1507  assert(request->_numOutstandingPackets > 0);
1508  // There are memory requests packets in flight already.
1509  // This may happen if the store was not complete the
1510  // first time this load got executed. Signal the senderSate
1511  // that response packets should be discarded.
1512  request->discard();
1513  }
1514 
1515  WritebackEvent *wb = new WritebackEvent(load_inst, data_pkt,
1516  this);
1517 
1518  // We'll say this has a 1 cycle load-store forwarding latency
1519  // for now.
1520  // @todo: Need to make this a parameter.
1521  cpu->schedule(wb, curTick());
1522 
1523  // Don't need to do anything special for split loads.
1524  ++stats.forwLoads;
1525 
1526  return NoFault;
1527  } else if (
1529  // If it's already been written back, then don't worry about
1530  // stalling on it.
1531  if (store_it->completed()) {
1532  panic("Should not check one of these");
1533  continue;
1534  }
1535 
1536  // Must stall load and force it to retry, so long as it's the
1537  // oldest load that needs to do so.
1538  if (!stalled ||
1539  (stalled &&
1540  load_inst->seqNum <
1541  loadQueue[stallingLoadIdx].instruction()->seqNum)) {
1542  stalled = true;
1543  stallingStoreIsn = store_it->instruction()->seqNum;
1544  stallingLoadIdx = load_idx;
1545  }
1546 
1547  // Tell IQ/mem dep unit that this instruction will need to be
1548  // rescheduled eventually
1549  iewStage->rescheduleMemInst(load_inst);
1550  load_inst->clearIssued();
1551  load_inst->effAddrValid(false);
1553 
1554  // Do not generate a writeback event as this instruction is not
1555  // complete.
1556  DPRINTF(LSQUnit, "Load-store forwarding mis-match. "
1557  "Store idx %i to load addr %#x\n",
1558  store_it._idx, request->mainReq()->getVaddr());
1559 
1560  // Must discard the request.
1561  request->discard();
1562  load_entry.setRequest(nullptr);
1563  return NoFault;
1564  }
1565  }
1566  }
1567 
1568  // If there's no forwarding case, then go access memory
1569  DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %s\n",
1570  load_inst->seqNum, load_inst->pcState());
1571 
1572  // Allocate memory if this is the first time a load is issued.
1573  if (!load_inst->memData) {
1574  load_inst->memData = new uint8_t[request->mainReq()->getSize()];
1575  }
1576 
1577 
1578  // hardware transactional memory
1579  if (request->mainReq()->isHTMCmd()) {
1580  // this is a simple sanity check
1581  // the Ruby cache controller will set
1582  // memData to 0x0ul if successful.
1583  *load_inst->memData = (uint64_t) 0x1ull;
1584  }
1585 
1586  // For now, load throughput is constrained by the number of
1587  // load FUs only, and loads do not consume a cache port (only
1588  // stores do).
1589  // @todo We should account for cache port contention
1590  // and arbitrate between loads and stores.
1591 
1592  // if we the cache is not blocked, do cache access
1593  request->buildPackets();
1594  request->sendPacketToCache();
1595  if (!request->isSent())
1596  iewStage->blockMemInst(load_inst);
1597 
1598  return NoFault;
1599 }
1600 
1601 Fault
1602 LSQUnit::write(LSQRequest *request, uint8_t *data, ssize_t store_idx)
1603 {
1604  assert(storeQueue[store_idx].valid());
1605 
1606  DPRINTF(LSQUnit, "Doing write to store idx %i, addr %#x | storeHead:%i "
1607  "[sn:%llu]\n",
1608  store_idx - 1, request->req()->getPaddr(), storeQueue.head() - 1,
1609  storeQueue[store_idx].instruction()->seqNum);
1610 
1611  storeQueue[store_idx].setRequest(request);
1612  unsigned size = request->_size;
1613  storeQueue[store_idx].size() = size;
1614  bool store_no_data =
1615  request->mainReq()->getFlags() & Request::STORE_NO_DATA;
1616  storeQueue[store_idx].isAllZeros() = store_no_data;
1617  assert(size <= SQEntry::DataSize || store_no_data);
1618 
1619  // copy data into the storeQueue only if the store request has valid data
1620  if (!(request->req()->getFlags() & Request::CACHE_BLOCK_ZERO) &&
1621  !request->req()->isCacheMaintenance() &&
1622  !request->req()->isAtomic())
1623  memcpy(storeQueue[store_idx].data(), data, size);
1624 
1625  // This function only writes the data to the store queue, so no fault
1626  // can happen here.
1627  return NoFault;
1628 }
1629 
1630 InstSeqNum
1632 {
1633  if (loadQueue.front().valid())
1634  return loadQueue.front().instruction()->seqNum;
1635  else
1636  return 0;
1637 }
1638 
1639 InstSeqNum
1641 {
1642  if (storeQueue.front().valid())
1643  return storeQueue.front().instruction()->seqNum;
1644  else
1645  return 0;
1646 }
1647 
1648 } // namespace o3
1649 } // namespace gem5
#define DPRINTF(x,...)
Definition: trace.hh:186
const char data[]
virtual ThreadContext * getContext(int tn)
Given a thread num get tho thread context for it.
Definition: base.hh:284
unsigned numContexts()
Get the number of thread contexts available.
Definition: base.hh:288
unsigned int cacheLineSize() const
Get the cache line size of the system.
Definition: base.hh:380
bool switchedOut() const
Determine if the CPU is switched out.
Definition: base.hh:356
virtual void handleLockedSnoop(PacketPtr pkt, Addr cacheBlockMask)
Definition: isa.hh:107
iterator getIterator(size_t idx)
Return an iterator to an index in the queue.
Tick clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
Cycles ticksToCycles(Tick t) const
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:79
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:294
Addr getAddr() const
Definition: packet.hh:805
void setHtmTransactionFailedInCache(const HtmCacheFailure ret_code)
Stipulates that this packet/request has returned from the cache hierarchy in a failed transaction.
Definition: packet.cc:493
void print(std::ostream &o, int verbosity=0, const std::string &prefix="") const
Definition: packet.cc:368
void dataStatic(T *p)
Set the data pointer to the following value that should not be freed.
Definition: packet.hh:1162
SenderState * senderState
This packet's sender state.
Definition: packet.hh:544
HtmCacheFailure getHtmTransactionFailedInCacheRC() const
If a packet/request has returned from the cache hierarchy in a failed transaction,...
Definition: packet.cc:509
bool isHtmTransactional() const
Returns whether or not this packet/request originates in the CPU executing in transactional mode,...
Definition: packet.cc:523
bool isWrite() const
Definition: packet.hh:593
uint64_t getHtmTransactionUid() const
If a packet/request originates in a CPU executing in transactional mode, i.e.
Definition: packet.cc:529
RequestPtr req
A pointer to the original request.
Definition: packet.hh:376
void setHtmTransactional(uint64_t val)
Stipulates that this packet/request originates in the CPU executing in transactional mode,...
Definition: packet.cc:516
bool isInvalidate() const
Definition: packet.hh:608
bool htmTransactionFailedInCache() const
Returns whether or not this packet/request has returned from the cache hierarchy in a failed transact...
Definition: packet.cc:503
T * data
The stored pointer.
Definition: refcnt.hh:146
T * get() const
Directly access the pointer itself without taking a reference.
Definition: refcnt.hh:227
A RequestPort is a specialisation of a Port, which implements the default protocol for the three diff...
Definition: port.hh:79
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
Definition: port.hh:495
@ LLSC
The request is a Load locked/store conditional.
Definition: request.hh:156
@ CACHE_BLOCK_ZERO
This is a write that is targeted and zeroing an entire cache block.
Definition: request.hh:143
static const FlagsType STORE_NO_DATA
Definition: request.hh:260
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual BaseISA * getIsaPtr() const =0
virtual BaseHTMCheckpointPtr & getHtmCheckpointPtr()=0
O3CPU class, has each of the stages (fetch through commit) within it, as well as all of the time buff...
Definition: cpu.hh:94
gem5::Checker< DynInstPtr > * checker
Pointer to the checker, which can dynamically verify instruction results at run time.
Definition: cpu.hh:524
std::vector< ThreadState * > thread
Pointers to all of the threads in the CPU.
Definition: cpu.hh:530
void activityThisCycle()
Records that there was time buffer activity this cycle.
Definition: cpu.hh:485
ProbePointArg< std::pair< DynInstPtr, PacketPtr > > * ppDataAccessComplete
Definition: cpu.hh:174
BaseMMU * mmu
Definition: cpu.hh:110
gem5::ThreadContext * tcBase(ThreadID tid)
Returns a pointer to a thread context.
Definition: cpu.hh:512
void wakeCPU()
Wakes the CPU, rescheduling the CPU if it's not already active.
Definition: cpu.cc:1399
IEW handles both single threaded and SMT IEW (issue/execute/writeback).
Definition: iew.hh:88
void instToCommit(const DynInstPtr &inst)
Sends an instruction to commit through the time buffer.
Definition: iew.cc:567
void blockMemInst(const DynInstPtr &inst)
Moves memory instruction onto the list of cache blocked instructions.
Definition: iew.cc:555
void activityThisCycle()
Reports to the CPU that there is activity this cycle.
Definition: iew.cc:809
void wakeCPU()
Tells the CPU to wakeup if it has descheduled itself due to no activity.
Definition: iew.cc:803
void rescheduleMemInst(const DynInstPtr &inst)
Tells memory dependence unit that a memory instruction needs to be rescheduled.
Definition: iew.cc:543
std::string name() const
Returns the name of the IEW stage.
Definition: iew.cc:118
void checkMisprediction(const DynInstPtr &inst)
Check misprediction
Definition: iew.cc:1591
bool updateLSQNextCycle
Records if the LSQ needs to be updated on the next cycle, so that IEW knows if there will be activity...
Definition: iew.hh:365
void replayMemInst(const DynInstPtr &inst)
Re-executes all rescheduled memory instructions.
Definition: iew.cc:549
void setRequest(LSQRequest *r)
Definition: lsq_unit.hh:138
const DynInstPtr & instruction() const
Definition: lsq_unit.hh:145
static constexpr size_t DataSize
Definition: lsq_unit.hh:167
Writeback event, specifically for when stores forward data to loads.
Definition: lsq_unit.hh:412
WritebackEvent(const DynInstPtr &_inst, PacketPtr pkt, LSQUnit *lsq_ptr)
Constructs a writeback event.
Definition: lsq_unit.cc:64
const char * description() const
Returns the description of this event.
Definition: lsq_unit.cc:86
void process()
Processes the writeback event.
Definition: lsq_unit.cc:74
Class that implements the actual LQ and SQ for each specific thread.
Definition: lsq_unit.hh:89
void insertStore(const DynInstPtr &store_inst)
Inserts a store instruction.
Definition: lsq_unit.cc:379
Fault write(LSQRequest *requst, uint8_t *data, ssize_t store_idx)
Executes the store at the given index.
Definition: lsq_unit.cc:1602
Addr cacheBlockMask
Address Mask for a cache block (e.g.
Definition: lsq_unit.hh:479
IEW * iewStage
Pointer to the IEW stage.
Definition: lsq_unit.hh:402
bool isStoreBlocked
Whehter or not a store is blocked due to the memory system.
Definition: lsq_unit.hh:497
void takeOverFrom()
Takes over from another CPU's thread.
Definition: lsq_unit.cc:297
bool checkLoads
Should loads be checked for dependency issues.
Definition: lsq_unit.hh:461
Fault read(LSQRequest *request, ssize_t load_idx)
Executes the load at the given index.
Definition: lsq_unit.cc:1317
bool storeInFlight
Whether or not a store is in flight.
Definition: lsq_unit.hh:500
CPU * cpu
Pointer to the CPU.
Definition: lsq_unit.hh:399
InstSeqNum getStoreHeadSeqNum()
Returns the sequence number of the head store instruction.
Definition: lsq_unit.cc:1640
InstSeqNum getLoadHeadSeqNum()
Returns the sequence number of the head load instruction.
Definition: lsq_unit.cc:1631
unsigned depCheckShift
The number of places to shift addresses in the LSQ before checking for dependency violations.
Definition: lsq_unit.hh:458
void storePostSend()
Handles completing the send of a store to memory.
Definition: lsq_unit.cc:1043
RequestPort * dcachePort
Pointer to the dcache port.
Definition: lsq_unit.hh:408
InstSeqNum stallingStoreIsn
The store that causes the stall due to partial store to load forwarding.
Definition: lsq_unit.hh:489
bool isStalled()
Returns whether or not the LSQ unit is stalled.
Definition: lsq_unit.hh:562
void insertLoad(const DynInstPtr &load_inst)
Inserts a load instruction.
Definition: lsq_unit.cc:319
Fault executeStore(const DynInstPtr &inst)
Executes a store instruction.
Definition: lsq_unit.cc:657
void insert(const DynInstPtr &inst)
Inserts an instruction.
Definition: lsq_unit.cc:303
bool checkStaleTranslations() const
Definition: lsq_unit.cc:1256
uint64_t getLatestHtmUid() const
Definition: lsq_unit.cc:1036
void schedule(Event &ev, Tick when)
Schedule event for the cpu.
Definition: lsq_unit.cc:1306
void writebackStores()
Writes back stores.
Definition: lsq_unit.cc:789
Fault checkViolations(typename LoadQueue::iterator &loadIt, const DynInstPtr &inst)
Check for ordering violations in the LSQ.
Definition: lsq_unit.cc:510
StoreQueue storeQueue
The store queue.
Definition: lsq_unit.hh:449
Fault executeLoad(const DynInstPtr &inst)
Executes a load instruction.
Definition: lsq_unit.cc:590
void commitLoad()
Commits the head load.
Definition: lsq_unit.cc:719
LSQUnit(uint32_t lqEntries, uint32_t sqEntries)
Constructs an LSQ unit.
Definition: lsq_unit.cc:192
void completeStore(typename StoreQueue::iterator store_idx)
Completes the store at the specified index.
Definition: lsq_unit.cc:1136
void drainSanityCheck() const
Perform sanity checks after a drain.
Definition: lsq_unit.cc:287
void setDcachePort(RequestPort *dcache_port)
Sets the pointer to the dcache port.
Definition: lsq_unit.cc:281
unsigned int cacheLineSize()
Definition: lsq_unit.cc:1311
void resetState()
Reset the LSQ state.
Definition: lsq_unit.cc:226
unsigned numFreeStoreEntries()
Returns the number of free SQ entries.
Definition: lsq_unit.cc:418
uint64_t lastRetiredHtmUid
Definition: lsq_unit.hh:471
void dumpInsts() const
Debugging function to dump instructions in the LSQ.
Definition: lsq_unit.cc:1283
bool stalled
Whether or not the LSQ is stalled.
Definition: lsq_unit.hh:485
ssize_t stallingLoadIdx
The index of the above store.
Definition: lsq_unit.hh:491
LoadQueue loadQueue
The load queue.
Definition: lsq_unit.hh:452
PacketPtr retryPkt
The packet that needs to be retried.
Definition: lsq_unit.hh:494
void init(CPU *cpu_ptr, IEW *iew_ptr, const BaseO3CPUParams &params, LSQ *lsq_ptr, unsigned id)
Initializes the LSQ unit with the specified number of entries.
Definition: lsq_unit.cc:203
DynInstPtr getMemDepViolator()
Returns the memory ordering violator.
Definition: lsq_unit.cc:400
DynInstPtr memDepViolator
The oldest load that caused a memory ordering violation.
Definition: lsq_unit.hh:503
void squash(const InstSeqNum &squashed_num)
Squashes all instructions younger than a specific sequence number.
Definition: lsq_unit.cc:921
std::string name() const
Returns the name of the LSQ unit.
Definition: lsq_unit.cc:245
void checkSnoop(PacketPtr pkt)
Check if an incoming invalidate hits in the lsq on a load that might have issued out of order wrt ano...
Definition: lsq_unit.cc:427
static constexpr auto MaxDataBytes
Definition: lsq_unit.hh:91
void recvRetry()
Handles doing the retry.
Definition: lsq_unit.cc:1274
int storesToWB
The number of store instructions in the SQ waiting to writeback.
Definition: lsq_unit.hh:464
unsigned numFreeLoadEntries()
Returns the number of free LQ entries.
Definition: lsq_unit.cc:410
bool trySendPacket(bool isLoad, PacketPtr data_pkt)
Attempts to send a packet to the cache.
Definition: lsq_unit.cc:1199
void writeback(const DynInstPtr &inst, PacketPtr pkt)
Writes back the instruction, sending it to IEW.
Definition: lsq_unit.cc:1074
StoreQueue::iterator storeWBIt
The index of the first instruction that may be ready to be written back, and has not yet been written...
Definition: lsq_unit.hh:476
BaseMMU * getMMUPtr()
Definition: lsq_unit.cc:1308
void writebackBlockedStore()
Try to finish a previously blocked write back attempt.
Definition: lsq_unit.cc:779
void commitLoads(InstSeqNum &youngest_inst)
Commits loads older than a specific sequence number.
Definition: lsq_unit.cc:742
gem5::o3::LSQUnit::LSQUnitStats stats
void completeDataAccess(PacketPtr pkt)
Completes the data access that has been returned from the memory system.
Definition: lsq_unit.cc:105
void startStaleTranslationFlush()
Definition: lsq_unit.cc:1241
LSQ * lsq
Pointer to the LSQ.
Definition: lsq_unit.hh:405
bool needsTSO
Flag for memory model.
Definition: lsq_unit.hh:506
void commitStores(InstSeqNum &youngest_inst)
Commits stores older than a specific sequence number.
Definition: lsq_unit.cc:753
ThreadID lsqID
The LSQUnit thread id.
Definition: lsq_unit.hh:446
bool recvTimingResp(PacketPtr pkt)
Handles writing back and completing the load or store that has returned from memory.
Definition: lsq_unit.cc:92
Memory operation metadata.
Definition: lsq.hh:190
virtual bool recvTimingResp(PacketPtr pkt)=0
virtual void buildPackets()=0
virtual RequestPtr mainReq()
Definition: lsq.hh:378
virtual bool isCacheBlockHit(Addr blockAddr, Addr cacheBlockMask)=0
Test if the request accesses a particular cache line.
void discard()
The request is discarded (e.g.
Definition: lsq.hh:518
PacketPtr packet(int idx=0)
Definition: lsq.hh:368
uint32_t _numOutstandingPackets
Definition: lsq.hh:258
void packetNotSent()
Update the status to reflect that a packet was not sent.
Definition: lsq.hh:446
const uint32_t _size
Definition: lsq.hh:255
bool isReleased()
Test if the LSQRequest has been released, i.e.
Definition: lsq.hh:402
bool isAnyOutstandingRequest()
Test if there is any in-flight translation or mem access request.
Definition: lsq.hh:388
virtual void sendPacketToCache()=0
bool isSplit() const
Definition: lsq.hh:409
void packetSent()
Update the status to reflect that a packet was sent.
Definition: lsq.hh:437
bool needWBToRegister() const
Definition: lsq.hh:415
RequestPtr req(int idx=0)
Definition: lsq.hh:362
const DynInstPtr & instruction()
Definition: lsq.hh:334
virtual PacketPtr mainPacket()
Definition: lsq.hh:371
bool cacheBlocked() const
Is D-cache blocked?
Definition: lsq.cc:186
void cachePortBusy(bool is_load)
Another store port is in use.
Definition: lsq.cc:210
bool cachePortAvailable(bool is_load) const
Is any store port available to use?
Definition: lsq.cc:198
Derived & flags(Flags _flags)
Set the flags and marks this stat to print at the end of simulation.
Definition: statistics.hh:358
void sample(const U &v, int n=1)
Add a value to the distribtion n times.
Definition: statistics.hh:1328
Distribution & init(Counter min, Counter max, Counter bkt)
Set the parameters of this distribution.
Definition: statistics.hh:2113
Statistics container.
Definition: group.hh:94
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition: group.hh:75
size_t size() const
size_t tail() const
void pop_front(size_t num_elem=1)
Circularly increase the head pointer.
size_t head() const
bool empty() const
Is the queue empty?
void pop_back()
Circularly decrease the tail pointer.
void advance_tail()
Increases the tail by one.
bool full() const
Is the queue full? A queue is full if the head is the 0^{th} element and the tail is the (size-1)^{th...
iterator begin()
Iterators.
size_t capacity() const
void schedule(Event &event, Tick when)
Definition: eventq.hh:1019
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
void addStatGroup(const char *name, Group *block)
Add a stat block as a child of this block.
Definition: group.cc:117
Bitfield< 7 > i
Definition: misc_types.hh:67
Bitfield< 9 > e
Definition: misc_types.hh:65
Bitfield< 33 > id
Definition: misc_types.hh:257
Bitfield< 4 > x
Definition: pagetable.hh:61
static constexpr int MaxThreads
Definition: limits.hh:38
ProbePointArg< PacketInfo > Packet
Packet probe point.
Definition: mem.hh:109
const FlagsType nozero
Don't print if this is zero.
Definition: info.hh:68
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
std::shared_ptr< FaultBase > Fault
Definition: types.hh:248
void cprintf(const char *format, const Args &...args)
Definition: cprintf.hh:155
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
std::string htmFailureToStr(HtmFailureFaultCause cause)
Convert enum into string to be used for debug purposes.
Definition: htm.cc:44
uint64_t Tick
Tick count type.
Definition: types.hh:58
HtmCacheFailure
Definition: htm.hh:60
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:161
constexpr decltype(nullptr) NoFault
Definition: types.hh:253
HtmFailureFaultCause
Definition: htm.hh:48
uint64_t InstSeqNum
Definition: inst_seq.hh:40
const std::string to_string(sc_enc enc)
Definition: sc_fxdefs.cc:60
Declaration of the Packet class.
Declaration of a request, the overall memory request consisting of the parts of the request that are ...
statistics::Scalar blockedByCache
Number of times the LSQ is blocked due to the cache.
Definition: lsq_unit.hh:536
statistics::Scalar forwLoads
Total number of loads forwaded from LSQ stores.
Definition: lsq_unit.hh:517
LSQUnitStats(statistics::Group *parent)
Definition: lsq_unit.cc:254
statistics::Scalar ignoredResponses
Total number of responses from the memory system that are ignored due to the instruction already bein...
Definition: lsq_unit.hh:524
statistics::Distribution loadToUse
Distribution of cycle latency between the first time a load is issued and its completion.
Definition: lsq_unit.hh:540
statistics::Scalar rescheduledLoads
Number of loads that were rescheduled.
Definition: lsq_unit.hh:533
statistics::Scalar squashedStores
Total number of squashed stores.
Definition: lsq_unit.hh:530
statistics::Scalar squashedLoads
Total number of squashed loads.
Definition: lsq_unit.hh:520
statistics::Scalar memOrderViolation
Tota number of memory ordering violations.
Definition: lsq_unit.hh:527

Generated on Wed Dec 21 2022 10:22:31 for gem5 by doxygen 1.9.1