gem5  v21.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
lsq_unit_impl.hh
Go to the documentation of this file.
1 
2 /*
3  * Copyright (c) 2010-2014, 2017-2020 ARM Limited
4  * Copyright (c) 2013 Advanced Micro Devices, Inc.
5  * All rights reserved
6  *
7  * The license below extends only to copyright in the software and shall
8  * not be construed as granting a license to any other intellectual
9  * property including but not limited to intellectual property relating
10  * to a hardware implementation of the functionality of the software
11  * licensed hereunder. You may use the software subject to the license
12  * terms below provided that you ensure that this notice is replicated
13  * unmodified and in its entirety in all distributions of the software,
14  * modified or unmodified, in source code or in binary form.
15  *
16  * Copyright (c) 2004-2005 The Regents of The University of Michigan
17  * All rights reserved.
18  *
19  * Redistribution and use in source and binary forms, with or without
20  * modification, are permitted provided that the following conditions are
21  * met: redistributions of source code must retain the above copyright
22  * notice, this list of conditions and the following disclaimer;
23  * redistributions in binary form must reproduce the above copyright
24  * notice, this list of conditions and the following disclaimer in the
25  * documentation and/or other materials provided with the distribution;
26  * neither the name of the copyright holders nor the names of its
27  * contributors may be used to endorse or promote products derived from
28  * this software without specific prior written permission.
29  *
30  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
36  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41  */
42 
43 #ifndef __CPU_O3_LSQ_UNIT_IMPL_HH__
44 #define __CPU_O3_LSQ_UNIT_IMPL_HH__
45 
47 #include "arch/locked_mem.hh"
48 #include "base/str.hh"
49 #include "config/the_isa.hh"
50 #include "cpu/checker/cpu.hh"
51 #include "cpu/o3/lsq.hh"
52 #include "cpu/o3/lsq_unit.hh"
53 #include "debug/Activity.hh"
54 #include "debug/HtmCpu.hh"
55 #include "debug/IEW.hh"
56 #include "debug/LSQUnit.hh"
57 #include "debug/O3PipeView.hh"
58 #include "mem/packet.hh"
59 #include "mem/request.hh"
60 
61 template<class Impl>
63  PacketPtr _pkt, LSQUnit *lsq_ptr)
64  : Event(Default_Pri, AutoDelete),
65  inst(_inst), pkt(_pkt), lsqPtr(lsq_ptr)
66 {
67  assert(_inst->savedReq);
68  _inst->savedReq->writebackScheduled();
69 }
70 
71 template<class Impl>
72 void
74 {
75  assert(!lsqPtr->cpu->switchedOut());
76 
77  lsqPtr->writeback(inst, pkt);
78 
79  assert(inst->savedReq);
80  inst->savedReq->writebackDone();
81  delete pkt;
82 }
83 
84 template<class Impl>
85 const char *
87 {
88  return "Store writeback";
89 }
90 
91 template <class Impl>
92 bool
94 {
95  auto senderState = dynamic_cast<LSQSenderState*>(pkt->senderState);
96  LSQRequest* req = senderState->request();
97  assert(req != nullptr);
98  bool ret = true;
99  /* Check that the request is still alive before any further action. */
100  if (senderState->alive()) {
101  ret = req->recvTimingResp(pkt);
102  } else {
103  senderState->outstanding--;
104  }
105  return ret;
106 
107 }
108 
109 template<class Impl>
110 void
112 {
113  LSQSenderState *state = dynamic_cast<LSQSenderState *>(pkt->senderState);
114  DynInstPtr inst = state->inst;
115 
116  // hardware transactional memory
117  // sanity check
118  if (pkt->isHtmTransactional() && !inst->isSquashed()) {
119  assert(inst->getHtmTransactionUid() == pkt->getHtmTransactionUid());
120  }
121 
122  // if in a HTM transaction, it's possible
123  // to abort within the cache hierarchy.
124  // This is signalled back to the processor
125  // through responses to memory requests.
126  if (pkt->htmTransactionFailedInCache()) {
127  // cannot do this for write requests because
128  // they cannot tolerate faults
129  const HtmCacheFailure htm_rc =
131  if(pkt->isWrite()) {
132  DPRINTF(HtmCpu,
133  "store notification (ignored) of HTM transaction failure "
134  "in cache - addr=0x%lx - rc=%s - htmUid=%d\n",
135  pkt->getAddr(), htmFailureToStr(htm_rc),
136  pkt->getHtmTransactionUid());
137  } else {
138  HtmFailureFaultCause fail_reason =
140 
141  if (htm_rc == HtmCacheFailure::FAIL_SELF) {
142  fail_reason = HtmFailureFaultCause::SIZE;
143  } else if (htm_rc == HtmCacheFailure::FAIL_REMOTE) {
144  fail_reason = HtmFailureFaultCause::MEMORY;
145  } else if (htm_rc == HtmCacheFailure::FAIL_OTHER) {
146  // these are likely loads that were issued out of order
147  // they are faulted here, but it's unlikely that these will
148  // ever reach the commit head.
149  fail_reason = HtmFailureFaultCause::OTHER;
150  } else {
151  panic("HTM error - unhandled return code from cache (%s)",
152  htmFailureToStr(htm_rc));
153  }
154 
155  inst->fault =
156  std::make_shared<GenericHtmFailureFault>(
157  inst->getHtmTransactionUid(),
158  fail_reason);
159 
160  DPRINTF(HtmCpu,
161  "load notification of HTM transaction failure "
162  "in cache - pc=%s - addr=0x%lx - "
163  "rc=%u - htmUid=%d\n",
164  inst->pcState(), pkt->getAddr(),
165  htmFailureToStr(htm_rc), pkt->getHtmTransactionUid());
166  }
167  }
168 
169  cpu->ppDataAccessComplete->notify(std::make_pair(inst, pkt));
170 
171  /* Notify the sender state that the access is complete (for ownership
172  * tracking). */
173  state->complete();
174 
175  assert(!cpu->switchedOut());
176  if (!inst->isSquashed()) {
177  if (state->needWB) {
178  // Only loads, store conditionals and atomics perform the writeback
179  // after receving the response from the memory
180  assert(inst->isLoad() || inst->isStoreConditional() ||
181  inst->isAtomic());
182 
183  // hardware transactional memory
184  if (pkt->htmTransactionFailedInCache()) {
185  state->request()->mainPacket()->setHtmTransactionFailedInCache(
187  }
188 
189  writeback(inst, state->request()->mainPacket());
190  if (inst->isStore() || inst->isAtomic()) {
191  auto ss = dynamic_cast<SQSenderState*>(state);
192  ss->writebackDone();
193  completeStore(ss->idx);
194  }
195  } else if (inst->isStore()) {
196  // This is a regular store (i.e., not store conditionals and
197  // atomics), so it can complete without writing back
198  completeStore(dynamic_cast<SQSenderState*>(state)->idx);
199  }
200  }
201 }
202 
203 template <class Impl>
204 LSQUnit<Impl>::LSQUnit(uint32_t lqEntries, uint32_t sqEntries)
205  : lsqID(-1), storeQueue(sqEntries+1), loadQueue(lqEntries+1),
206  loads(0), stores(0), storesToWB(0),
207  htmStarts(0), htmStops(0),
209  cacheBlockMask(0), stalled(false),
210  isStoreBlocked(false), storeInFlight(false), hasPendingRequest(false),
211  pendingRequest(nullptr), stats(nullptr)
212 {
213 }
214 
215 template<class Impl>
216 void
217 LSQUnit<Impl>::init(O3CPU *cpu_ptr, IEW *iew_ptr,
218  const DerivO3CPUParams &params, LSQ *lsq_ptr, unsigned id)
219 {
220  lsqID = id;
221 
222  cpu = cpu_ptr;
223  iewStage = iew_ptr;
224 
225  lsq = lsq_ptr;
226 
227  cpu->addStatGroup(csprintf("lsq%i", lsqID).c_str(), &stats);
228 
229  DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",lsqID);
230 
231  depCheckShift = params.LSQDepCheckShift;
232  checkLoads = params.LSQCheckLoads;
233  needsTSO = params.needsTSO;
234 
235  resetState();
236 }
237 
238 
239 template<class Impl>
240 void
242 {
243  loads = stores = storesToWB = 0;
244 
245  // hardware transactional memory
246  // nesting depth
247  htmStarts = htmStops = 0;
248 
249  storeWBIt = storeQueue.begin();
250 
251  retryPkt = NULL;
252  memDepViolator = NULL;
253 
254  stalled = false;
255 
256  cacheBlockMask = ~(cpu->cacheLineSize() - 1);
257 }
258 
259 template<class Impl>
260 std::string
262 {
263  if (Impl::MaxThreads == 1) {
264  return iewStage->name() + ".lsq";
265  } else {
266  return iewStage->name() + ".lsq.thread" + std::to_string(lsqID);
267  }
268 }
269 
270 template <class Impl>
272  : Stats::Group(parent),
273  ADD_STAT(forwLoads, UNIT_COUNT,
274  "Number of loads that had data forwarded from stores"),
275  ADD_STAT(squashedLoads, UNIT_COUNT,
276  "Number of loads squashed"),
277  ADD_STAT(ignoredResponses, UNIT_COUNT,
278  "Number of memory responses ignored because the instruction is "
279  "squashed"),
280  ADD_STAT(memOrderViolation, UNIT_COUNT,
281  "Number of memory ordering violations"),
282  ADD_STAT(squashedStores, UNIT_COUNT, "Number of stores squashed"),
283  ADD_STAT(rescheduledLoads, UNIT_COUNT,
284  "Number of loads that were rescheduled"),
285  ADD_STAT(blockedByCache, UNIT_COUNT,
286  "Number of times an access to memory failed due to the cache "
287  "being blocked")
288 {
289 }
290 
291 template<class Impl>
292 void
294 {
295  dcachePort = dcache_port;
296 }
297 
298 template<class Impl>
299 void
301 {
302  for (int i = 0; i < loadQueue.capacity(); ++i)
303  assert(!loadQueue[i].valid());
304 
305  assert(storesToWB == 0);
306  assert(!retryPkt);
307 }
308 
309 template<class Impl>
310 void
312 {
313  resetState();
314 }
315 
316 template <class Impl>
317 void
319 {
320  assert(inst->isMemRef());
321 
322  assert(inst->isLoad() || inst->isStore() || inst->isAtomic());
323 
324  if (inst->isLoad()) {
325  insertLoad(inst);
326  } else {
327  insertStore(inst);
328  }
329 
330  inst->setInLSQ();
331 }
332 
333 template <class Impl>
334 void
336 {
337  assert(!loadQueue.full());
338  assert(loads < loadQueue.capacity());
339 
340  DPRINTF(LSQUnit, "Inserting load PC %s, idx:%i [sn:%lli]\n",
341  load_inst->pcState(), loadQueue.tail(), load_inst->seqNum);
342 
343  /* Grow the queue. */
345 
346  load_inst->sqIt = storeQueue.end();
347 
348  assert(!loadQueue.back().valid());
349  loadQueue.back().set(load_inst);
350  load_inst->lqIdx = loadQueue.tail();
351  assert(load_inst->lqIdx > 0);
352  load_inst->lqIt = loadQueue.getIterator(load_inst->lqIdx);
353 
354  ++loads;
355 
356  // hardware transactional memory
357  // transactional state and nesting depth must be tracked
358  // in the in-order part of the core.
359  if (load_inst->isHtmStart()) {
360  htmStarts++;
361  DPRINTF(HtmCpu, ">> htmStarts++ (%d) : htmStops (%d)\n",
363 
364  const int htm_depth = htmStarts - htmStops;
365  const auto& htm_cpt = cpu->tcBase(lsqID)->getHtmCheckpointPtr();
366  auto htm_uid = htm_cpt->getHtmUid();
367 
368  // for debugging purposes
369  if (!load_inst->inHtmTransactionalState()) {
370  htm_uid = htm_cpt->newHtmUid();
371  DPRINTF(HtmCpu, "generating new htmUid=%u\n", htm_uid);
372  if (htm_depth != 1) {
373  DPRINTF(HtmCpu,
374  "unusual HTM transactional depth (%d)"
375  " possibly caused by mispeculation - htmUid=%u\n",
376  htm_depth, htm_uid);
377  }
378  }
379  load_inst->setHtmTransactionalState(htm_uid, htm_depth);
380  }
381 
382  if (load_inst->isHtmStop()) {
383  htmStops++;
384  DPRINTF(HtmCpu, ">> htmStarts (%d) : htmStops++ (%d)\n",
386 
387  if (htmStops==1 && htmStarts==0) {
388  DPRINTF(HtmCpu,
389  "htmStops==1 && htmStarts==0. "
390  "This generally shouldn't happen "
391  "(unless due to misspeculation)\n");
392  }
393  }
394 }
395 
396 template <class Impl>
397 void
399 {
400  // Make sure it is not full before inserting an instruction.
401  assert(!storeQueue.full());
402  assert(stores < storeQueue.capacity());
403 
404  DPRINTF(LSQUnit, "Inserting store PC %s, idx:%i [sn:%lli]\n",
405  store_inst->pcState(), storeQueue.tail(), store_inst->seqNum);
406  storeQueue.advance_tail();
407 
408  store_inst->sqIdx = storeQueue.tail();
409  store_inst->lqIdx = loadQueue.tail() + 1;
410  assert(store_inst->lqIdx > 0);
411  store_inst->lqIt = loadQueue.end();
412 
413  storeQueue.back().set(store_inst);
414 
415  ++stores;
416 }
417 
418 template <class Impl>
419 typename Impl::DynInstPtr
421 {
422  DynInstPtr temp = memDepViolator;
423 
424  memDepViolator = NULL;
425 
426  return temp;
427 }
428 
429 template <class Impl>
430 unsigned
432 {
433  //LQ has an extra dummy entry to differentiate
434  //empty/full conditions. Subtract 1 from the free entries.
435  DPRINTF(LSQUnit, "LQ size: %d, #loads occupied: %d\n",
436  1 + loadQueue.capacity(), loads);
437  return loadQueue.capacity() - loads;
438 }
439 
440 template <class Impl>
441 unsigned
443 {
444  //SQ has an extra dummy entry to differentiate
445  //empty/full conditions. Subtract 1 from the free entries.
446  DPRINTF(LSQUnit, "SQ size: %d, #stores occupied: %d\n",
447  1 + storeQueue.capacity(), stores);
448  return storeQueue.capacity() - stores;
449 
450  }
451 
452 template <class Impl>
453 void
455 {
456  // Should only ever get invalidations in here
457  assert(pkt->isInvalidate());
458 
459  DPRINTF(LSQUnit, "Got snoop for address %#x\n", pkt->getAddr());
460 
461  for (int x = 0; x < cpu->numContexts(); x++) {
462  ThreadContext *tc = cpu->getContext(x);
463  bool no_squash = cpu->thread[x]->noSquashFromTC;
464  cpu->thread[x]->noSquashFromTC = true;
466  cpu->thread[x]->noSquashFromTC = no_squash;
467  }
468 
469  if (loadQueue.empty())
470  return;
471 
472  auto iter = loadQueue.begin();
473 
474  Addr invalidate_addr = pkt->getAddr() & cacheBlockMask;
475 
476  DynInstPtr ld_inst = iter->instruction();
477  assert(ld_inst);
478  LSQRequest *req = iter->request();
479 
480  // Check that this snoop didn't just invalidate our lock flag
481  if (ld_inst->effAddrValid() &&
482  req->isCacheBlockHit(invalidate_addr, cacheBlockMask)
483  && ld_inst->memReqFlags & Request::LLSC)
484  TheISA::handleLockedSnoopHit(ld_inst.get());
485 
486  bool force_squash = false;
487 
488  while (++iter != loadQueue.end()) {
489  ld_inst = iter->instruction();
490  assert(ld_inst);
491  req = iter->request();
492  if (!ld_inst->effAddrValid() || ld_inst->strictlyOrdered())
493  continue;
494 
495  DPRINTF(LSQUnit, "-- inst [sn:%lli] to pktAddr:%#x\n",
496  ld_inst->seqNum, invalidate_addr);
497 
498  if (force_squash ||
499  req->isCacheBlockHit(invalidate_addr, cacheBlockMask)) {
500  if (needsTSO) {
501  // If we have a TSO system, as all loads must be ordered with
502  // all other loads, this load as well as *all* subsequent loads
503  // need to be squashed to prevent possible load reordering.
504  force_squash = true;
505  }
506  if (ld_inst->possibleLoadViolation() || force_squash) {
507  DPRINTF(LSQUnit, "Conflicting load at addr %#x [sn:%lli]\n",
508  pkt->getAddr(), ld_inst->seqNum);
509 
510  // Mark the load for re-execution
511  ld_inst->fault = std::make_shared<ReExec>();
512  req->setStateToFault();
513  } else {
514  DPRINTF(LSQUnit, "HitExternal Snoop for addr %#x [sn:%lli]\n",
515  pkt->getAddr(), ld_inst->seqNum);
516 
517  // Make sure that we don't lose a snoop hitting a LOCKED
518  // address since the LOCK* flags don't get updated until
519  // commit.
520  if (ld_inst->memReqFlags & Request::LLSC)
521  TheISA::handleLockedSnoopHit(ld_inst.get());
522 
523  // If a older load checks this and it's true
524  // then we might have missed the snoop
525  // in which case we need to invalidate to be sure
526  ld_inst->hitExternalSnoop(true);
527  }
528  }
529  }
530  return;
531 }
532 
533 template <class Impl>
534 Fault
535 LSQUnit<Impl>::checkViolations(typename LoadQueue::iterator& loadIt,
536  const DynInstPtr& inst)
537 {
538  Addr inst_eff_addr1 = inst->effAddr >> depCheckShift;
539  Addr inst_eff_addr2 = (inst->effAddr + inst->effSize - 1) >> depCheckShift;
540 
546  while (loadIt != loadQueue.end()) {
547  DynInstPtr ld_inst = loadIt->instruction();
548  if (!ld_inst->effAddrValid() || ld_inst->strictlyOrdered()) {
549  ++loadIt;
550  continue;
551  }
552 
553  Addr ld_eff_addr1 = ld_inst->effAddr >> depCheckShift;
554  Addr ld_eff_addr2 =
555  (ld_inst->effAddr + ld_inst->effSize - 1) >> depCheckShift;
556 
557  if (inst_eff_addr2 >= ld_eff_addr1 && inst_eff_addr1 <= ld_eff_addr2) {
558  if (inst->isLoad()) {
559  // If this load is to the same block as an external snoop
560  // invalidate that we've observed then the load needs to be
561  // squashed as it could have newer data
562  if (ld_inst->hitExternalSnoop()) {
563  if (!memDepViolator ||
564  ld_inst->seqNum < memDepViolator->seqNum) {
565  DPRINTF(LSQUnit, "Detected fault with inst [sn:%lli] "
566  "and [sn:%lli] at address %#x\n",
567  inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
568  memDepViolator = ld_inst;
569 
571 
572  return std::make_shared<GenericISA::M5PanicFault>(
573  "Detected fault with inst [sn:%lli] and "
574  "[sn:%lli] at address %#x\n",
575  inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
576  }
577  }
578 
579  // Otherwise, mark the load has a possible load violation
580  // and if we see a snoop before it's commited, we need to squash
581  ld_inst->possibleLoadViolation(true);
582  DPRINTF(LSQUnit, "Found possible load violation at addr: %#x"
583  " between instructions [sn:%lli] and [sn:%lli]\n",
584  inst_eff_addr1, inst->seqNum, ld_inst->seqNum);
585  } else {
586  // A load/store incorrectly passed this store.
587  // Check if we already have a violator, or if it's newer
588  // squash and refetch.
589  if (memDepViolator && ld_inst->seqNum > memDepViolator->seqNum)
590  break;
591 
592  DPRINTF(LSQUnit, "Detected fault with inst [sn:%lli] and "
593  "[sn:%lli] at address %#x\n",
594  inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
595  memDepViolator = ld_inst;
596 
598 
599  return std::make_shared<GenericISA::M5PanicFault>(
600  "Detected fault with "
601  "inst [sn:%lli] and [sn:%lli] at address %#x\n",
602  inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
603  }
604  }
605 
606  ++loadIt;
607  }
608  return NoFault;
609 }
610 
611 
612 
613 
614 template <class Impl>
615 Fault
617 {
618  // Execute a specific load.
619  Fault load_fault = NoFault;
620 
621  DPRINTF(LSQUnit, "Executing load PC %s, [sn:%lli]\n",
622  inst->pcState(), inst->seqNum);
623 
624  assert(!inst->isSquashed());
625 
626  load_fault = inst->initiateAcc();
627 
628  if (load_fault == NoFault && !inst->readMemAccPredicate()) {
629  assert(inst->readPredicate());
630  inst->setExecuted();
631  inst->completeAcc(nullptr);
632  iewStage->instToCommit(inst);
633  iewStage->activityThisCycle();
634  return NoFault;
635  }
636 
637  if (inst->isTranslationDelayed() && load_fault == NoFault)
638  return load_fault;
639 
640  if (load_fault != NoFault && inst->translationCompleted() &&
641  inst->savedReq->isPartialFault() && !inst->savedReq->isComplete()) {
642  assert(inst->savedReq->isSplit());
643  // If we have a partial fault where the mem access is not complete yet
644  // then the cache must have been blocked. This load will be re-executed
645  // when the cache gets unblocked. We will handle the fault when the
646  // mem access is complete.
647  return NoFault;
648  }
649 
650  // If the instruction faulted or predicated false, then we need to send it
651  // along to commit without the instruction completing.
652  if (load_fault != NoFault || !inst->readPredicate()) {
653  // Send this instruction to commit, also make sure iew stage
654  // realizes there is activity. Mark it as executed unless it
655  // is a strictly ordered load that needs to hit the head of
656  // commit.
657  if (!inst->readPredicate())
658  inst->forwardOldRegs();
659  DPRINTF(LSQUnit, "Load [sn:%lli] not executed from %s\n",
660  inst->seqNum,
661  (load_fault != NoFault ? "fault" : "predication"));
662  if (!(inst->hasRequest() && inst->strictlyOrdered()) ||
663  inst->isAtCommit()) {
664  inst->setExecuted();
665  }
666  iewStage->instToCommit(inst);
667  iewStage->activityThisCycle();
668  } else {
669  if (inst->effAddrValid()) {
670  auto it = inst->lqIt;
671  ++it;
672 
673  if (checkLoads)
674  return checkViolations(it, inst);
675  }
676  }
677 
678  return load_fault;
679 }
680 
681 template <class Impl>
682 Fault
684 {
685  // Make sure that a store exists.
686  assert(stores != 0);
687 
688  int store_idx = store_inst->sqIdx;
689 
690  DPRINTF(LSQUnit, "Executing store PC %s [sn:%lli]\n",
691  store_inst->pcState(), store_inst->seqNum);
692 
693  assert(!store_inst->isSquashed());
694 
695  // Check the recently completed loads to see if any match this store's
696  // address. If so, then we have a memory ordering violation.
697  typename LoadQueue::iterator loadIt = store_inst->lqIt;
698 
699  Fault store_fault = store_inst->initiateAcc();
700 
701  if (store_inst->isTranslationDelayed() &&
702  store_fault == NoFault)
703  return store_fault;
704 
705  if (!store_inst->readPredicate()) {
706  DPRINTF(LSQUnit, "Store [sn:%lli] not executed from predication\n",
707  store_inst->seqNum);
708  store_inst->forwardOldRegs();
709  return store_fault;
710  }
711 
712  if (storeQueue[store_idx].size() == 0) {
713  DPRINTF(LSQUnit,"Fault on Store PC %s, [sn:%lli], Size = 0\n",
714  store_inst->pcState(), store_inst->seqNum);
715 
716  return store_fault;
717  }
718 
719  assert(store_fault == NoFault);
720 
721  if (store_inst->isStoreConditional() || store_inst->isAtomic()) {
722  // Store conditionals and Atomics need to set themselves as able to
723  // writeback if we haven't had a fault by here.
724  storeQueue[store_idx].canWB() = true;
725 
726  ++storesToWB;
727  }
728 
729  return checkViolations(loadIt, store_inst);
730 
731 }
732 
733 template <class Impl>
734 void
736 {
737  assert(loadQueue.front().valid());
738 
739  DPRINTF(LSQUnit, "Committing head load instruction, PC %s\n",
740  loadQueue.front().instruction()->pcState());
741 
742  loadQueue.front().clear();
744 
745  --loads;
746 }
747 
748 template <class Impl>
749 void
751 {
752  assert(loads == 0 || loadQueue.front().valid());
753 
754  while (loads != 0 && loadQueue.front().instruction()->seqNum
755  <= youngest_inst) {
756  commitLoad();
757  }
758 }
759 
760 template <class Impl>
761 void
763 {
764  assert(stores == 0 || storeQueue.front().valid());
765 
766  /* Forward iterate the store queue (age order). */
767  for (auto& x : storeQueue) {
768  assert(x.valid());
769  // Mark any stores that are now committed and have not yet
770  // been marked as able to write back.
771  if (!x.canWB()) {
772  if (x.instruction()->seqNum > youngest_inst) {
773  break;
774  }
775  DPRINTF(LSQUnit, "Marking store as able to write back, PC "
776  "%s [sn:%lli]\n",
777  x.instruction()->pcState(),
778  x.instruction()->seqNum);
779 
780  x.canWB() = true;
781 
782  ++storesToWB;
783  }
784  }
785 }
786 
787 template <class Impl>
788 void
790 {
791  assert(isStoreBlocked);
792  storeWBIt->request()->sendPacketToCache();
793  if (storeWBIt->request()->isSent()){
794  storePostSend();
795  }
796 }
797 
798 template <class Impl>
799 void
801 {
802  if (isStoreBlocked) {
803  DPRINTF(LSQUnit, "Writing back blocked store\n");
805  }
806 
807  while (storesToWB > 0 &&
809  storeWBIt->valid() &&
810  storeWBIt->canWB() &&
811  ((!needsTSO) || (!storeInFlight)) &&
812  lsq->cachePortAvailable(false)) {
813 
814  if (isStoreBlocked) {
815  DPRINTF(LSQUnit, "Unable to write back any more stores, cache"
816  " is blocked!\n");
817  break;
818  }
819 
820  // Store didn't write any data so no need to write it back to
821  // memory.
822  if (storeWBIt->size() == 0) {
823  /* It is important that the preincrement happens at (or before)
824  * the call, as the the code of completeStore checks
825  * storeWBIt. */
827  continue;
828  }
829 
830  if (storeWBIt->instruction()->isDataPrefetch()) {
831  storeWBIt++;
832  continue;
833  }
834 
835  assert(storeWBIt->hasRequest());
836  assert(!storeWBIt->committed());
837 
838  DynInstPtr inst = storeWBIt->instruction();
839  LSQRequest* req = storeWBIt->request();
840 
841  // Process store conditionals or store release after all previous
842  // stores are completed
843  if ((req->mainRequest()->isLLSC() ||
844  req->mainRequest()->isRelease()) &&
845  (storeWBIt.idx() != storeQueue.head())) {
846  DPRINTF(LSQUnit, "Store idx:%i PC:%s to Addr:%#x "
847  "[sn:%lli] is %s%s and not head of the queue\n",
848  storeWBIt.idx(), inst->pcState(),
849  req->request()->getPaddr(), inst->seqNum,
850  req->mainRequest()->isLLSC() ? "SC" : "",
851  req->mainRequest()->isRelease() ? "/Release" : "");
852  break;
853  }
854 
855  storeWBIt->committed() = true;
856 
857  assert(!inst->memData);
858  inst->memData = new uint8_t[req->_size];
859 
860  if (storeWBIt->isAllZeros())
861  memset(inst->memData, 0, req->_size);
862  else
863  memcpy(inst->memData, storeWBIt->data(), req->_size);
864 
865 
866  if (req->senderState() == nullptr) {
867  SQSenderState *state = new SQSenderState(storeWBIt);
868  state->isLoad = false;
869  state->needWB = false;
870  state->inst = inst;
871 
872  req->senderState(state);
873  if (inst->isStoreConditional() || inst->isAtomic()) {
874  /* Only store conditionals and atomics need a writeback. */
875  state->needWB = true;
876  }
877  }
878  req->buildPackets();
879 
880  DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%s "
881  "to Addr:%#x, data:%#x [sn:%lli]\n",
882  storeWBIt.idx(), inst->pcState(),
883  req->request()->getPaddr(), (int)*(inst->memData),
884  inst->seqNum);
885 
886  // @todo: Remove this SC hack once the memory system handles it.
887  if (inst->isStoreConditional()) {
888  // Disable recording the result temporarily. Writing to
889  // misc regs normally updates the result, but this is not
890  // the desired behavior when handling store conditionals.
891  inst->recordResult(false);
892  bool success = TheISA::handleLockedWrite(inst.get(),
893  req->request(), cacheBlockMask);
894  inst->recordResult(true);
895  req->packetSent();
896 
897  if (!success) {
898  req->complete();
899  // Instantly complete this store.
900  DPRINTF(LSQUnit, "Store conditional [sn:%lli] failed. "
901  "Instantly completing it.\n",
902  inst->seqNum);
903  PacketPtr new_pkt = new Packet(*req->packet());
904  WritebackEvent *wb = new WritebackEvent(inst,
905  new_pkt, this);
906  cpu->schedule(wb, curTick() + 1);
908  if (!storeQueue.empty())
909  storeWBIt++;
910  else
911  storeWBIt = storeQueue.end();
912  continue;
913  }
914  }
915 
916  if (req->request()->isLocalAccess()) {
917  assert(!inst->isStoreConditional());
918  assert(!inst->inHtmTransactionalState());
919  ThreadContext *thread = cpu->tcBase(lsqID);
920  PacketPtr main_pkt = new Packet(req->mainRequest(),
922  main_pkt->dataStatic(inst->memData);
923  req->request()->localAccessor(thread, main_pkt);
924  delete main_pkt;
926  storeWBIt++;
927  continue;
928  }
929  /* Send to cache */
930  req->sendPacketToCache();
931 
932  /* If successful, do the post send */
933  if (req->isSent()) {
934  storePostSend();
935  } else {
936  DPRINTF(LSQUnit, "D-Cache became blocked when writing [sn:%lli], "
937  "will retry later\n",
938  inst->seqNum);
939  }
940  }
941  assert(stores >= 0 && storesToWB >= 0);
942 }
943 
944 template <class Impl>
945 void
946 LSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
947 {
948  DPRINTF(LSQUnit, "Squashing until [sn:%lli]!"
949  "(Loads:%i Stores:%i)\n", squashed_num, loads, stores);
950 
951  while (loads != 0 &&
952  loadQueue.back().instruction()->seqNum > squashed_num) {
953  DPRINTF(LSQUnit,"Load Instruction PC %s squashed, "
954  "[sn:%lli]\n",
955  loadQueue.back().instruction()->pcState(),
956  loadQueue.back().instruction()->seqNum);
957 
958  if (isStalled() && loadQueue.tail() == stallingLoadIdx) {
959  stalled = false;
960  stallingStoreIsn = 0;
961  stallingLoadIdx = 0;
962  }
963 
964  // hardware transactional memory
965  // Squashing instructions can alter the transaction nesting depth
966  // and must be corrected before fetching resumes.
967  if (loadQueue.back().instruction()->isHtmStart())
968  {
969  htmStarts = (--htmStarts < 0) ? 0 : htmStarts;
970  DPRINTF(HtmCpu, ">> htmStarts-- (%d) : htmStops (%d)\n",
972  }
973  if (loadQueue.back().instruction()->isHtmStop())
974  {
975  htmStops = (--htmStops < 0) ? 0 : htmStops;
976  DPRINTF(HtmCpu, ">> htmStarts (%d) : htmStops-- (%d)\n",
978  }
979  // Clear the smart pointer to make sure it is decremented.
980  loadQueue.back().instruction()->setSquashed();
981  loadQueue.back().clear();
982 
983  --loads;
984 
987  }
988 
989  // hardware transactional memory
990  // scan load queue (from oldest to youngest) for most recent valid htmUid
991  auto scan_it = loadQueue.begin();
992  uint64_t in_flight_uid = 0;
993  while (scan_it != loadQueue.end()) {
994  if (scan_it->instruction()->isHtmStart() &&
995  !scan_it->instruction()->isSquashed()) {
996  in_flight_uid = scan_it->instruction()->getHtmTransactionUid();
997  DPRINTF(HtmCpu, "loadQueue[%d]: found valid HtmStart htmUid=%u\n",
998  scan_it._idx, in_flight_uid);
999  }
1000  scan_it++;
1001  }
1002  // If there's a HtmStart in the pipeline then use its htmUid,
1003  // otherwise use the most recently committed uid
1004  const auto& htm_cpt = cpu->tcBase(lsqID)->getHtmCheckpointPtr();
1005  if (htm_cpt) {
1006  const uint64_t old_local_htm_uid = htm_cpt->getHtmUid();
1007  uint64_t new_local_htm_uid;
1008  if (in_flight_uid > 0)
1009  new_local_htm_uid = in_flight_uid;
1010  else
1011  new_local_htm_uid = lastRetiredHtmUid;
1012 
1013  if (old_local_htm_uid != new_local_htm_uid) {
1014  DPRINTF(HtmCpu, "flush: lastRetiredHtmUid=%u\n",
1016  DPRINTF(HtmCpu, "flush: resetting localHtmUid=%u\n",
1017  new_local_htm_uid);
1018 
1019  htm_cpt->setHtmUid(new_local_htm_uid);
1020  }
1021  }
1022 
1023  if (memDepViolator && squashed_num < memDepViolator->seqNum) {
1024  memDepViolator = NULL;
1025  }
1026 
1027  while (stores != 0 &&
1028  storeQueue.back().instruction()->seqNum > squashed_num) {
1029  // Instructions marked as can WB are already committed.
1030  if (storeQueue.back().canWB()) {
1031  break;
1032  }
1033 
1034  DPRINTF(LSQUnit,"Store Instruction PC %s squashed, "
1035  "idx:%i [sn:%lli]\n",
1036  storeQueue.back().instruction()->pcState(),
1037  storeQueue.tail(), storeQueue.back().instruction()->seqNum);
1038 
1039  // I don't think this can happen. It should have been cleared
1040  // by the stalling load.
1041  if (isStalled() &&
1042  storeQueue.back().instruction()->seqNum == stallingStoreIsn) {
1043  panic("Is stalled should have been cleared by stalling load!\n");
1044  stalled = false;
1045  stallingStoreIsn = 0;
1046  }
1047 
1048  // Clear the smart pointer to make sure it is decremented.
1049  storeQueue.back().instruction()->setSquashed();
1050 
1051  // Must delete request now that it wasn't handed off to
1052  // memory. This is quite ugly. @todo: Figure out the proper
1053  // place to really handle request deletes.
1054  storeQueue.back().clear();
1055  --stores;
1056 
1057  storeQueue.pop_back();
1059  }
1060 }
1061 
1062 template <class Impl>
1063 void
1065 {
1066  if (isStalled() &&
1067  storeWBIt->instruction()->seqNum == stallingStoreIsn) {
1068  DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
1069  "load idx:%i\n",
1071  stalled = false;
1072  stallingStoreIsn = 0;
1073  iewStage->replayMemInst(loadQueue[stallingLoadIdx].instruction());
1074  }
1075 
1076  if (!storeWBIt->instruction()->isStoreConditional()) {
1077  // The store is basically completed at this time. This
1078  // only works so long as the checker doesn't try to
1079  // verify the value in memory for stores.
1080  storeWBIt->instruction()->setCompleted();
1081 
1082  if (cpu->checker) {
1083  cpu->checker->verify(storeWBIt->instruction());
1084  }
1085  }
1086 
1087  if (needsTSO) {
1088  storeInFlight = true;
1089  }
1090 
1091  storeWBIt++;
1092 }
1093 
1094 template <class Impl>
1095 void
1097 {
1098  iewStage->wakeCPU();
1099 
1100  // Squashed instructions do not need to complete their access.
1101  if (inst->isSquashed()) {
1102  assert (!inst->isStore() || inst->isStoreConditional());
1104  return;
1105  }
1106 
1107  if (!inst->isExecuted()) {
1108  inst->setExecuted();
1109 
1110  if (inst->fault == NoFault) {
1111  // Complete access to copy data to proper place.
1112  inst->completeAcc(pkt);
1113  } else {
1114  // If the instruction has an outstanding fault, we cannot complete
1115  // the access as this discards the current fault.
1116 
1117  // If we have an outstanding fault, the fault should only be of
1118  // type ReExec or - in case of a SplitRequest - a partial
1119  // translation fault
1120 
1121  // Unless it's a hardware transactional memory fault
1122  auto htm_fault = std::dynamic_pointer_cast<
1123  GenericHtmFailureFault>(inst->fault);
1124 
1125  if (!htm_fault) {
1126  assert(dynamic_cast<ReExec*>(inst->fault.get()) != nullptr ||
1127  inst->savedReq->isPartialFault());
1128 
1129  } else if (!pkt->htmTransactionFailedInCache()) {
1130  // Situation in which the instruction has a hardware transactional
1131  // memory fault but not the packet itself. This can occur with
1132  // ldp_uop microops since access is spread over multiple packets.
1133  DPRINTF(HtmCpu,
1134  "%s writeback with HTM failure fault, "
1135  "however, completing packet is not aware of "
1136  "transaction failure. cause=%s htmUid=%u\n",
1137  inst->staticInst->getName(),
1138  htmFailureToStr(htm_fault->getHtmFailureFaultCause()),
1139  htm_fault->getHtmUid());
1140  }
1141 
1142  DPRINTF(LSQUnit, "Not completing instruction [sn:%lli] access "
1143  "due to pending fault.\n", inst->seqNum);
1144  }
1145  }
1146 
1147  // Need to insert instruction into queue to commit
1148  iewStage->instToCommit(inst);
1149 
1150  iewStage->activityThisCycle();
1151 
1152  // see if this load changed the PC
1153  iewStage->checkMisprediction(inst);
1154 }
1155 
1156 template <class Impl>
1157 void
1159 {
1160  assert(store_idx->valid());
1161  store_idx->completed() = true;
1162  --storesToWB;
1163  // A bit conservative because a store completion may not free up entries,
1164  // but hopefully avoids two store completions in one cycle from making
1165  // the CPU tick twice.
1166  cpu->wakeCPU();
1167  cpu->activityThisCycle();
1168 
1169  /* We 'need' a copy here because we may clear the entry from the
1170  * store queue. */
1171  DynInstPtr store_inst = store_idx->instruction();
1172  if (store_idx == storeQueue.begin()) {
1173  do {
1174  storeQueue.front().clear();
1175  storeQueue.pop_front();
1176  --stores;
1177  } while (storeQueue.front().completed() &&
1178  !storeQueue.empty());
1179 
1180  iewStage->updateLSQNextCycle = true;
1181  }
1182 
1183  DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head "
1184  "idx:%i\n",
1185  store_inst->seqNum, store_idx.idx() - 1, storeQueue.head() - 1);
1186 
1187 #if TRACING_ON
1188  if (DTRACE(O3PipeView)) {
1189  store_inst->storeTick =
1190  curTick() - store_inst->fetchTick;
1191  }
1192 #endif
1193 
1194  if (isStalled() &&
1195  store_inst->seqNum == stallingStoreIsn) {
1196  DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
1197  "load idx:%i\n",
1199  stalled = false;
1200  stallingStoreIsn = 0;
1201  iewStage->replayMemInst(loadQueue[stallingLoadIdx].instruction());
1202  }
1203 
1204  store_inst->setCompleted();
1205 
1206  if (needsTSO) {
1207  storeInFlight = false;
1208  }
1209 
1210  // Tell the checker we've completed this instruction. Some stores
1211  // may get reported twice to the checker, but the checker can
1212  // handle that case.
1213  // Store conditionals cannot be sent to the checker yet, they have
1214  // to update the misc registers first which should take place
1215  // when they commit
1216  if (cpu->checker && !store_inst->isStoreConditional()) {
1217  cpu->checker->verify(store_inst);
1218  }
1219 }
1220 
1221 template <class Impl>
1222 bool
1224 {
1225  bool ret = true;
1226  bool cache_got_blocked = false;
1227 
1228  auto state = dynamic_cast<LSQSenderState*>(data_pkt->senderState);
1229 
1230  if (!lsq->cacheBlocked() &&
1231  lsq->cachePortAvailable(isLoad)) {
1232  if (!dcachePort->sendTimingReq(data_pkt)) {
1233  ret = false;
1234  cache_got_blocked = true;
1235  }
1236  } else {
1237  ret = false;
1238  }
1239 
1240  if (ret) {
1241  if (!isLoad) {
1242  isStoreBlocked = false;
1243  }
1244  lsq->cachePortBusy(isLoad);
1245  state->outstanding++;
1246  state->request()->packetSent();
1247  } else {
1248  if (cache_got_blocked) {
1249  lsq->cacheBlocked(true);
1251  }
1252  if (!isLoad) {
1253  assert(state->request() == storeWBIt->request());
1254  isStoreBlocked = true;
1255  }
1256  state->request()->packetNotSent();
1257  }
1258  return ret;
1259 }
1260 
1261 template <class Impl>
1262 void
1264 {
1265  if (isStoreBlocked) {
1266  DPRINTF(LSQUnit, "Receiving retry: blocked store\n");
1268  }
1269 }
1270 
1271 template <class Impl>
1272 void
1274 {
1275  cprintf("Load store queue: Dumping instructions.\n");
1276  cprintf("Load queue size: %i\n", loads);
1277  cprintf("Load queue: ");
1278 
1279  for (const auto& e: loadQueue) {
1280  const DynInstPtr &inst(e.instruction());
1281  cprintf("%s.[sn:%llu] ", inst->pcState(), inst->seqNum);
1282  }
1283  cprintf("\n");
1284 
1285  cprintf("Store queue size: %i\n", stores);
1286  cprintf("Store queue: ");
1287 
1288  for (const auto& e: storeQueue) {
1289  const DynInstPtr &inst(e.instruction());
1290  cprintf("%s.[sn:%llu] ", inst->pcState(), inst->seqNum);
1291  }
1292 
1293  cprintf("\n");
1294 }
1295 
1296 template <class Impl>
1297 unsigned int
1299 {
1300  return cpu->cacheLineSize();
1301 }
1302 
1303 #endif//__CPU_O3_LSQ_UNIT_IMPL_HH__
LSQUnit::insertLoad
void insertLoad(const DynInstPtr &load_inst)
Inserts a load instruction.
Definition: lsq_unit_impl.hh:335
LSQUnit::writebackBlockedStore
void writebackBlockedStore()
Try to finish a previously blocked write back attempt.
Definition: lsq_unit_impl.hh:789
ArmISA::handleLockedWrite
bool handleLockedWrite(XC *xc, const RequestPtr &req, Addr cacheBlockMask)
Definition: locked_mem.hh:111
LSQUnit::DynInstPtr
Impl::DynInstPtr DynInstPtr
Definition: lsq_unit.hh:84
LSQUnit::dumpInsts
void dumpInsts() const
Debugging function to dump instructions in the LSQ.
Definition: lsq_unit_impl.hh:1273
LSQUnit::commitLoad
void commitLoad()
Commits the head load.
Definition: lsq_unit_impl.hh:735
LSQUnit::depCheckShift
unsigned depCheckShift
The number of places to shift addresses in the LSQ before checking for dependency violations.
Definition: lsq_unit.hh:504
CircularQueue::advance_tail
void advance_tail()
Increases the tail by one.
Definition: circular_queue.hh:512
LSQUnit::LSQUnitStats::memOrderViolation
Stats::Scalar memOrderViolation
Tota number of memory ordering violations.
Definition: lsq_unit.hh:583
CircularQueue::iterator::dereferenceable
bool dereferenceable() const
Test dereferenceability.
Definition: circular_queue.hh:140
LSQUnit::pendingRequest
LSQRequest * pendingRequest
The packet that is pending free cache ports.
Definition: lsq_unit.hh:560
ArmISA::handleLockedSnoop
void handleLockedSnoop(XC *xc, PacketPtr pkt, Addr cacheBlockMask)
Definition: locked_mem.hh:62
Packet::getAddr
Addr getAddr() const
Definition: packet.hh:755
HtmCacheFailure::FAIL_OTHER
@ FAIL_OTHER
Packet::isHtmTransactional
bool isHtmTransactional() const
Returns whether or not this packet/request originates in the CPU executing in transactional mode,...
Definition: packet.cc:544
LSQUnit::storePostSend
void storePostSend()
Handles completing the send of a store to memory.
Definition: lsq_unit_impl.hh:1064
ArmISA::i
Bitfield< 7 > i
Definition: miscregs_types.hh:63
CircularQueue::getIterator
iterator getIterator(size_t idx)
Return an iterator to an index in the queue.
Definition: circular_queue.hh:589
LSQUnit::htmStarts
int htmStarts
Definition: lsq_unit.hh:518
LSQUnit::stallingStoreIsn
InstSeqNum stallingStoreIsn
The store that causes the stall due to partial store to load forwarding.
Definition: lsq_unit.hh:539
LSQUnit::iewStage
IEW * iewStage
Pointer to the IEW stage.
Definition: lsq_unit.hh:411
LSQUnit::recvTimingResp
bool recvTimingResp(PacketPtr pkt)
Handles writing back and completing the load or store that has returned from memory.
Definition: lsq_unit_impl.hh:93
sc_dt::to_string
const std::string to_string(sc_enc enc)
Definition: sc_fxdefs.cc:91
LSQUnit::O3CPU
Impl::O3CPU O3CPU
Definition: lsq_unit.hh:83
LSQUnit::cacheLineSize
unsigned int cacheLineSize()
Definition: lsq_unit_impl.hh:1298
CircularQueue::pop_back
void pop_back()
Circularly decrease the tail pointer.
Definition: circular_queue.hh:487
LSQUnit::cpu
O3CPU * cpu
Pointer to the CPU.
Definition: lsq_unit.hh:408
LSQUnit::isStalled
bool isStalled()
Returns whether or not the LSQ unit is stalled.
Definition: lsq_unit.hh:626
Packet::isInvalidate
bool isInvalidate() const
Definition: packet.hh:572
LSQUnit::checkSnoop
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_impl.hh:454
LSQUnit::getMemDepViolator
DynInstPtr getMemDepViolator()
Returns the memory ordering violator.
Definition: lsq_unit_impl.hh:420
DTRACE
#define DTRACE(x)
Definition: debug.hh:156
CircularQueue::begin
iterator begin()
Iterators.
Definition: circular_queue.hh:562
LSQUnit::storesToWB
int storesToWB
The number of store instructions in the SQ waiting to writeback.
Definition: lsq_unit.hh:514
HtmFailureFaultCause
HtmFailureFaultCause
Definition: htm.hh:44
LSQUnit::init
void init(O3CPU *cpu_ptr, IEW *iew_ptr, const DerivO3CPUParams &params, LSQ *lsq_ptr, unsigned id)
Initializes the LSQ unit with the specified number of entries.
Definition: lsq_unit_impl.hh:217
GenericHtmFailureFault
Definition: faults.hh:136
HtmCacheFailure::FAIL_REMOTE
@ FAIL_REMOTE
LSQUnit::writeback
void writeback(const DynInstPtr &inst, PacketPtr pkt)
Writes back the instruction, sending it to IEW.
Definition: lsq_unit_impl.hh:1096
LSQUnit::SQSenderState
Particularisation of the LSQSenderState to the SQ.
Definition: lsq_unit.hh:439
LSQUnit::storeInFlight
bool storeInFlight
Whether or not a store is in flight.
Definition: lsq_unit.hh:550
LSQUnit::commitLoads
void commitLoads(InstSeqNum &youngest_inst)
Commits loads older than a specific sequence number.
Definition: lsq_unit_impl.hh:750
CircularQueue::iterator
Iterator to the circular queue.
Definition: circular_queue.hh:82
LSQUnit::numFreeStoreEntries
unsigned numFreeStoreEntries()
Returns the number of free SQ entries.
Definition: lsq_unit_impl.hh:442
request.hh
packet.hh
LSQUnit::stores
int stores
The number of store instructions in the SQ.
Definition: lsq_unit.hh:512
LSQUnit::drainSanityCheck
void drainSanityCheck() const
Perform sanity checks after a drain.
Definition: lsq_unit_impl.hh:300
CircularQueue::full
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...
Definition: circular_queue.hh:555
LSQUnit::completeStore
void completeStore(typename StoreQueue::iterator store_idx)
Completes the store at the specified index.
Definition: lsq_unit_impl.hh:1158
str.hh
MemCmd::WriteReq
@ WriteReq
Definition: packet.hh:86
LSQUnit::LSQUnitStats::blockedByCache
Stats::Scalar blockedByCache
Number of times the LSQ is blocked due to the cache.
Definition: lsq_unit.hh:592
CircularQueue::tail
size_t tail() const
Definition: circular_queue.hh:453
LSQUnit::checkLoads
bool checkLoads
Should loads be checked for dependency issues.
Definition: lsq_unit.hh:507
LSQUnit::resetState
void resetState()
Reset the LSQ state.
Definition: lsq_unit_impl.hh:241
CircularQueue::back
reference back()
Definition: circular_queue.hh:443
LSQUnit
Class that implements the actual LQ and SQ for each specific thread.
Definition: lsq_unit.hh:78
LSQUnit::takeOverFrom
void takeOverFrom()
Takes over from another CPU's thread.
Definition: lsq_unit_impl.hh:311
LSQUnit::LSQUnitStats::ignoredResponses
Stats::Scalar ignoredResponses
Total number of responses from the memory system that are ignored due to the instruction already bein...
Definition: lsq_unit.hh:580
LSQUnit::lsq
LSQ * lsq
Pointer to the LSQ.
Definition: lsq_unit.hh:414
LSQUnit::loadQueue
LoadQueue loadQueue
The load queue.
Definition: lsq_unit.hh:498
ArmISA::ss
Bitfield< 21 > ss
Definition: miscregs_types.hh:56
CircularQueue::front
reference front()
Definition: circular_queue.hh:438
HtmFailureFaultCause::OTHER
@ OTHER
ThreadContext
ThreadContext is the external interface to all thread state for anything outside of the CPU.
Definition: thread_context.hh:88
LSQUnit::hasPendingRequest
bool hasPendingRequest
Whether or not there is a packet that couldn't be sent because of a lack of cache ports.
Definition: lsq_unit.hh:557
LSQ
Definition: lsq.hh:68
ArmISA::handleLockedSnoopHit
void handleLockedSnoopHit(XC *xc)
Definition: locked_mem.hh:101
RequestPort::sendTimingReq
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
Definition: port.hh:492
Event
Definition: eventq.hh:248
LSQ::cachePortAvailable
bool cachePortAvailable(bool is_load) const
Is any store port available to use?
Definition: lsq_impl.hh:194
LSQUnit::WritebackEvent::WritebackEvent
WritebackEvent(const DynInstPtr &_inst, PacketPtr pkt, LSQUnit *lsq_ptr)
Constructs a writeback event.
Definition: lsq_unit_impl.hh:62
cprintf
void cprintf(const char *format, const Args &...args)
Definition: cprintf.hh:152
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:237
ADD_STAT
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition: group.hh:71
Fault
std::shared_ptr< FaultBase > Fault
Definition: types.hh:246
CircularQueue::iterator::idx
size_t idx() const
OutputIterator has no extra requirements.
Definition: circular_queue.hh:383
cpu.hh
LSQ::cachePortBusy
void cachePortBusy(bool is_load)
Another store port is in use.
Definition: lsq_impl.hh:207
LSQUnit::WritebackEvent::process
void process()
Processes the writeback event.
Definition: lsq_unit_impl.hh:73
LSQUnit::commitStores
void commitStores(InstSeqNum &youngest_inst)
Commits stores older than a specific sequence number.
Definition: lsq_unit_impl.hh:762
LSQUnit::insert
void insert(const DynInstPtr &inst)
Inserts an instruction.
Definition: lsq_unit_impl.hh:318
LSQUnit::storeWBIt
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:526
CircularQueue::end
iterator end()
Definition: circular_queue.hh:577
LSQUnit::writebackStores
void writebackStores()
Writes back stores.
Definition: lsq_unit_impl.hh:800
ReExec
Definition: faults.hh:88
LSQUnit::numFreeLoadEntries
unsigned numFreeLoadEntries()
Returns the number of free LQ entries.
Definition: lsq_unit_impl.hh:431
RiscvISA::x
Bitfield< 3 > x
Definition: pagetable.hh:70
RequestPort
A RequestPort is a specialisation of a Port, which implements the default protocol for the three diff...
Definition: port.hh:74
LSQUnit::loads
int loads
The number of load instructions in the LQ.
Definition: lsq_unit.hh:510
InstSeqNum
uint64_t InstSeqNum
Definition: inst_seq.hh:37
UNIT_COUNT
#define UNIT_COUNT
Definition: units.hh:49
NoFault
constexpr decltype(nullptr) NoFault
Definition: types.hh:251
LSQUnit::stallingLoadIdx
int stallingLoadIdx
The index of the above store.
Definition: lsq_unit.hh:541
LSQUnit::lsqID
ThreadID lsqID
The LSQUnit thread id.
Definition: lsq_unit.hh:492
ProbePoints::Packet
ProbePointArg< PacketInfo > Packet
Packet probe point.
Definition: mem.hh:103
Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:148
LSQUnit::trySendPacket
bool trySendPacket(bool isLoad, PacketPtr data_pkt)
Attempts to send a packet to the cache.
Definition: lsq_unit_impl.hh:1223
LSQUnit::htmStops
int htmStops
Definition: lsq_unit.hh:519
HtmCacheFailure
HtmCacheFailure
Definition: htm.hh:56
Packet::htmTransactionFailedInCache
bool htmTransactionFailedInCache() const
Returns whether or not this packet/request has returned from the cache hierarchy in a failed transact...
Definition: packet.cc:524
LSQUnit::dcachePort
RequestPort * dcachePort
Pointer to the dcache port.
Definition: lsq_unit.hh:417
LSQUnit::retryPkt
PacketPtr retryPkt
The packet that needs to be retried.
Definition: lsq_unit.hh:544
CircularQueue::pop_front
void pop_front(size_t num_elem=1)
Circularly increase the head pointer.
Definition: circular_queue.hh:474
ArmISA::e
Bitfield< 9 > e
Definition: miscregs_types.hh:61
Packet::getHtmTransactionUid
uint64_t getHtmTransactionUid() const
If a packet/request originates in a CPU executing in transactional mode, i.e.
Definition: packet.cc:550
LSQUnit::recvRetry
void recvRetry()
Handles doing the retry.
Definition: lsq_unit_impl.hh:1263
CircularQueue::empty
bool empty() const
Is the queue empty?
Definition: circular_queue.hh:545
LSQUnit::LSQRequest
typename Impl::CPUPol::LSQ::LSQRequest LSQRequest
Definition: lsq_unit.hh:90
LSQUnit::memDepViolator
DynInstPtr memDepViolator
The oldest load that caused a memory ordering violation.
Definition: lsq_unit.hh:553
LSQUnit::name
std::string name() const
Returns the name of the LSQ unit.
Definition: lsq_unit_impl.hh:261
LSQUnit::setDcachePort
void setDcachePort(RequestPort *dcache_port)
Sets the pointer to the dcache port.
Definition: lsq_unit_impl.hh:293
CircularQueue::capacity
size_t capacity() const
Definition: circular_queue.hh:458
LSQUnit::LSQUnitStats::squashedStores
Stats::Scalar squashedStores
Total number of squashed stores.
Definition: lsq_unit.hh:586
LSQUnit::executeStore
Fault executeStore(const DynInstPtr &inst)
Executes a store instruction.
Definition: lsq_unit_impl.hh:683
Packet::dataStatic
void dataStatic(T *p)
Set the data pointer to the following value that should not be freed.
Definition: packet.hh:1108
Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:258
Stats::Group
Statistics container.
Definition: group.hh:87
LSQUnit::needsTSO
bool needsTSO
Flag for memory model.
Definition: lsq_unit.hh:563
Request::LLSC
@ LLSC
The request is a Load locked/store conditional.
Definition: request.hh:149
LSQUnit::insertStore
void insertStore(const DynInstPtr &store_inst)
Inserts a store instruction.
Definition: lsq_unit_impl.hh:398
LSQUnit::stalled
bool stalled
Whether or not the LSQ is stalled.
Definition: lsq_unit.hh:535
LSQUnit::completeDataAccess
void completeDataAccess(PacketPtr pkt)
Completes the data access that has been returned from the memory system.
Definition: lsq_unit_impl.hh:111
LSQUnit::storeQueue
CircularQueue< SQEntry > storeQueue
The store queue.
Definition: lsq_unit.hh:495
lsq_unit.hh
htmFailureToStr
std::string htmFailureToStr(HtmFailureFaultCause cause)
Convert enum into string to be used for debug purposes.
Definition: htm.cc:41
LSQUnit::LSQUnit
LSQUnit(uint32_t lqEntries, uint32_t sqEntries)
Constructs an LSQ unit.
Definition: lsq_unit_impl.hh:204
LSQUnit::LSQUnitStats::squashedLoads
Stats::Scalar squashedLoads
Total number of squashed loads.
Definition: lsq_unit.hh:576
Packet::isWrite
bool isWrite() const
Definition: packet.hh:558
LSQ::cacheBlocked
bool cacheBlocked() const
Is D-cache blocked?
Definition: lsq_impl.hh:180
LSQUnit::cacheBlockMask
Addr cacheBlockMask
Address Mask for a cache block (e.g.
Definition: lsq_unit.hh:529
Stats
Definition: statistics.cc:53
LSQUnit::isStoreBlocked
bool isStoreBlocked
Whehter or not a store is blocked due to the memory system.
Definition: lsq_unit.hh:547
curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:43
LSQUnit::lastRetiredHtmUid
uint64_t lastRetiredHtmUid
Definition: lsq_unit.hh:521
debugfaults.hh
Packet::senderState
SenderState * senderState
This packet's sender state.
Definition: packet.hh:509
LSQUnit::squash
void squash(const InstSeqNum &squashed_num)
Squashes all instructions younger than a specific sequence number.
Definition: lsq_unit_impl.hh:946
HtmFailureFaultCause::INVALID
@ INVALID
Packet::getHtmTransactionFailedInCacheRC
HtmCacheFailure getHtmTransactionFailedInCacheRC() const
If a packet/request has returned from the cache hierarchy in a failed transaction,...
Definition: packet.cc:530
LSQUnit::IEW
Impl::CPUPol::IEW IEW
Definition: lsq_unit.hh:85
lsq.hh
LSQUnit::LSQUnitStats::LSQUnitStats
LSQUnitStats(Stats::Group *parent)
Definition: lsq_unit_impl.hh:271
HtmFailureFaultCause::SIZE
@ SIZE
LSQUnit::executeLoad
Fault executeLoad(const DynInstPtr &inst)
Executes a load instruction.
Definition: lsq_unit_impl.hh:616
HtmFailureFaultCause::MEMORY
@ MEMORY
HtmCacheFailure::FAIL_SELF
@ FAIL_SELF
LSQUnit::WritebackEvent::description
const char * description() const
Returns the description of this event.
Definition: lsq_unit_impl.hh:86
csprintf
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:158
LSQUnit::stats
LSQUnit::LSQUnitStats stats
LSQUnit::LSQSenderState
typename LSQ::LSQSenderState LSQSenderState
Definition: lsq_unit.hh:89
LSQUnit::WritebackEvent
Writeback event, specifically for when stores forward data to loads.
Definition: lsq_unit.hh:457
ArmISA::id
Bitfield< 33 > id
Definition: miscregs_types.hh:247
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:171
LSQUnit::checkViolations
Fault checkViolations(typename LoadQueue::iterator &loadIt, const DynInstPtr &inst)
Check for ordering violations in the LSQ.
Definition: lsq_unit_impl.hh:535

Generated on Tue Mar 23 2021 19:41:25 for gem5 by doxygen 1.8.17