gem5  v20.1.0.0
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, DerivO3CPUParams *params,
218  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, "Number of loads that had data forwarded from"
274  " stores"),
275  ADD_STAT(squashedLoads, "Number of loads squashed"),
276  ADD_STAT(ignoredResponses, "Number of memory responses ignored"
277  " because the instruction is squashed"),
278  ADD_STAT(memOrderViolation, "Number of memory ordering violations"),
279  ADD_STAT(squashedStores, "Number of stores squashed"),
280  ADD_STAT(rescheduledLoads, "Number of loads that were rescheduled"),
281  ADD_STAT(blockedByCache, "Number of times an access to memory failed"
282  " due to the cache being blocked")
283 {
284 }
285 
286 template<class Impl>
287 void
289 {
290  dcachePort = dcache_port;
291 }
292 
293 template<class Impl>
294 void
296 {
297  for (int i = 0; i < loadQueue.capacity(); ++i)
298  assert(!loadQueue[i].valid());
299 
300  assert(storesToWB == 0);
301  assert(!retryPkt);
302 }
303 
304 template<class Impl>
305 void
307 {
308  resetState();
309 }
310 
311 template <class Impl>
312 void
314 {
315  assert(inst->isMemRef());
316 
317  assert(inst->isLoad() || inst->isStore() || inst->isAtomic());
318 
319  if (inst->isLoad()) {
320  insertLoad(inst);
321  } else {
322  insertStore(inst);
323  }
324 
325  inst->setInLSQ();
326 }
327 
328 template <class Impl>
329 void
331 {
332  assert(!loadQueue.full());
333  assert(loads < loadQueue.capacity());
334 
335  DPRINTF(LSQUnit, "Inserting load PC %s, idx:%i [sn:%lli]\n",
336  load_inst->pcState(), loadQueue.tail(), load_inst->seqNum);
337 
338  /* Grow the queue. */
340 
341  load_inst->sqIt = storeQueue.end();
342 
343  assert(!loadQueue.back().valid());
344  loadQueue.back().set(load_inst);
345  load_inst->lqIdx = loadQueue.tail();
346  load_inst->lqIt = loadQueue.getIterator(load_inst->lqIdx);
347 
348  ++loads;
349 
350  // hardware transactional memory
351  // transactional state and nesting depth must be tracked
352  // in the in-order part of the core.
353  if (load_inst->isHtmStart()) {
354  htmStarts++;
355  DPRINTF(HtmCpu, ">> htmStarts++ (%d) : htmStops (%d)\n",
357 
358  const int htm_depth = htmStarts - htmStops;
359  const auto& htm_cpt = cpu->tcBase(lsqID)->getHtmCheckpointPtr();
360  auto htm_uid = htm_cpt->getHtmUid();
361 
362  // for debugging purposes
363  if (!load_inst->inHtmTransactionalState()) {
364  htm_uid = htm_cpt->newHtmUid();
365  DPRINTF(HtmCpu, "generating new htmUid=%u\n", htm_uid);
366  if (htm_depth != 1) {
367  DPRINTF(HtmCpu,
368  "unusual HTM transactional depth (%d)"
369  " possibly caused by mispeculation - htmUid=%u\n",
370  htm_depth, htm_uid);
371  }
372  }
373  load_inst->setHtmTransactionalState(htm_uid, htm_depth);
374  }
375 
376  if (load_inst->isHtmStop()) {
377  htmStops++;
378  DPRINTF(HtmCpu, ">> htmStarts (%d) : htmStops++ (%d)\n",
380 
381  if (htmStops==1 && htmStarts==0) {
382  DPRINTF(HtmCpu,
383  "htmStops==1 && htmStarts==0. "
384  "This generally shouldn't happen "
385  "(unless due to misspeculation)\n");
386  }
387  }
388 }
389 
390 template <class Impl>
391 void
393 {
394  // Make sure it is not full before inserting an instruction.
395  assert(!storeQueue.full());
396  assert(stores < storeQueue.capacity());
397 
398  DPRINTF(LSQUnit, "Inserting store PC %s, idx:%i [sn:%lli]\n",
399  store_inst->pcState(), storeQueue.tail(), store_inst->seqNum);
400  storeQueue.advance_tail();
401 
402  store_inst->sqIdx = storeQueue.tail();
403  store_inst->lqIdx = loadQueue.moduloAdd(loadQueue.tail(), 1);
404  store_inst->lqIt = loadQueue.end();
405 
406  storeQueue.back().set(store_inst);
407 
408  ++stores;
409 }
410 
411 template <class Impl>
412 typename Impl::DynInstPtr
414 {
415  DynInstPtr temp = memDepViolator;
416 
417  memDepViolator = NULL;
418 
419  return temp;
420 }
421 
422 template <class Impl>
423 unsigned
425 {
426  //LQ has an extra dummy entry to differentiate
427  //empty/full conditions. Subtract 1 from the free entries.
428  DPRINTF(LSQUnit, "LQ size: %d, #loads occupied: %d\n",
429  1 + loadQueue.capacity(), loads);
430  return loadQueue.capacity() - loads;
431 }
432 
433 template <class Impl>
434 unsigned
436 {
437  //SQ has an extra dummy entry to differentiate
438  //empty/full conditions. Subtract 1 from the free entries.
439  DPRINTF(LSQUnit, "SQ size: %d, #stores occupied: %d\n",
440  1 + storeQueue.capacity(), stores);
441  return storeQueue.capacity() - stores;
442 
443  }
444 
445 template <class Impl>
446 void
448 {
449  // Should only ever get invalidations in here
450  assert(pkt->isInvalidate());
451 
452  DPRINTF(LSQUnit, "Got snoop for address %#x\n", pkt->getAddr());
453 
454  for (int x = 0; x < cpu->numContexts(); x++) {
455  ThreadContext *tc = cpu->getContext(x);
456  bool no_squash = cpu->thread[x]->noSquashFromTC;
457  cpu->thread[x]->noSquashFromTC = true;
459  cpu->thread[x]->noSquashFromTC = no_squash;
460  }
461 
462  if (loadQueue.empty())
463  return;
464 
465  auto iter = loadQueue.begin();
466 
467  Addr invalidate_addr = pkt->getAddr() & cacheBlockMask;
468 
469  DynInstPtr ld_inst = iter->instruction();
470  assert(ld_inst);
471  LSQRequest *req = iter->request();
472 
473  // Check that this snoop didn't just invalidate our lock flag
474  if (ld_inst->effAddrValid() &&
475  req->isCacheBlockHit(invalidate_addr, cacheBlockMask)
476  && ld_inst->memReqFlags & Request::LLSC)
477  TheISA::handleLockedSnoopHit(ld_inst.get());
478 
479  bool force_squash = false;
480 
481  while (++iter != loadQueue.end()) {
482  ld_inst = iter->instruction();
483  assert(ld_inst);
484  req = iter->request();
485  if (!ld_inst->effAddrValid() || ld_inst->strictlyOrdered())
486  continue;
487 
488  DPRINTF(LSQUnit, "-- inst [sn:%lli] to pktAddr:%#x\n",
489  ld_inst->seqNum, invalidate_addr);
490 
491  if (force_squash ||
492  req->isCacheBlockHit(invalidate_addr, cacheBlockMask)) {
493  if (needsTSO) {
494  // If we have a TSO system, as all loads must be ordered with
495  // all other loads, this load as well as *all* subsequent loads
496  // need to be squashed to prevent possible load reordering.
497  force_squash = true;
498  }
499  if (ld_inst->possibleLoadViolation() || force_squash) {
500  DPRINTF(LSQUnit, "Conflicting load at addr %#x [sn:%lli]\n",
501  pkt->getAddr(), ld_inst->seqNum);
502 
503  // Mark the load for re-execution
504  ld_inst->fault = std::make_shared<ReExec>();
505  req->setStateToFault();
506  } else {
507  DPRINTF(LSQUnit, "HitExternal Snoop for addr %#x [sn:%lli]\n",
508  pkt->getAddr(), ld_inst->seqNum);
509 
510  // Make sure that we don't lose a snoop hitting a LOCKED
511  // address since the LOCK* flags don't get updated until
512  // commit.
513  if (ld_inst->memReqFlags & Request::LLSC)
514  TheISA::handleLockedSnoopHit(ld_inst.get());
515 
516  // If a older load checks this and it's true
517  // then we might have missed the snoop
518  // in which case we need to invalidate to be sure
519  ld_inst->hitExternalSnoop(true);
520  }
521  }
522  }
523  return;
524 }
525 
526 template <class Impl>
527 Fault
528 LSQUnit<Impl>::checkViolations(typename LoadQueue::iterator& loadIt,
529  const DynInstPtr& inst)
530 {
531  Addr inst_eff_addr1 = inst->effAddr >> depCheckShift;
532  Addr inst_eff_addr2 = (inst->effAddr + inst->effSize - 1) >> depCheckShift;
533 
539  while (loadIt != loadQueue.end()) {
540  DynInstPtr ld_inst = loadIt->instruction();
541  if (!ld_inst->effAddrValid() || ld_inst->strictlyOrdered()) {
542  ++loadIt;
543  continue;
544  }
545 
546  Addr ld_eff_addr1 = ld_inst->effAddr >> depCheckShift;
547  Addr ld_eff_addr2 =
548  (ld_inst->effAddr + ld_inst->effSize - 1) >> depCheckShift;
549 
550  if (inst_eff_addr2 >= ld_eff_addr1 && inst_eff_addr1 <= ld_eff_addr2) {
551  if (inst->isLoad()) {
552  // If this load is to the same block as an external snoop
553  // invalidate that we've observed then the load needs to be
554  // squashed as it could have newer data
555  if (ld_inst->hitExternalSnoop()) {
556  if (!memDepViolator ||
557  ld_inst->seqNum < memDepViolator->seqNum) {
558  DPRINTF(LSQUnit, "Detected fault with inst [sn:%lli] "
559  "and [sn:%lli] at address %#x\n",
560  inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
561  memDepViolator = ld_inst;
562 
564 
565  return std::make_shared<GenericISA::M5PanicFault>(
566  "Detected fault with inst [sn:%lli] and "
567  "[sn:%lli] at address %#x\n",
568  inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
569  }
570  }
571 
572  // Otherwise, mark the load has a possible load violation
573  // and if we see a snoop before it's commited, we need to squash
574  ld_inst->possibleLoadViolation(true);
575  DPRINTF(LSQUnit, "Found possible load violation at addr: %#x"
576  " between instructions [sn:%lli] and [sn:%lli]\n",
577  inst_eff_addr1, inst->seqNum, ld_inst->seqNum);
578  } else {
579  // A load/store incorrectly passed this store.
580  // Check if we already have a violator, or if it's newer
581  // squash and refetch.
582  if (memDepViolator && ld_inst->seqNum > memDepViolator->seqNum)
583  break;
584 
585  DPRINTF(LSQUnit, "Detected fault with inst [sn:%lli] and "
586  "[sn:%lli] at address %#x\n",
587  inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
588  memDepViolator = ld_inst;
589 
591 
592  return std::make_shared<GenericISA::M5PanicFault>(
593  "Detected fault with "
594  "inst [sn:%lli] and [sn:%lli] at address %#x\n",
595  inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
596  }
597  }
598 
599  ++loadIt;
600  }
601  return NoFault;
602 }
603 
604 
605 
606 
607 template <class Impl>
608 Fault
610 {
611  using namespace TheISA;
612  // Execute a specific load.
613  Fault load_fault = NoFault;
614 
615  DPRINTF(LSQUnit, "Executing load PC %s, [sn:%lli]\n",
616  inst->pcState(), inst->seqNum);
617 
618  assert(!inst->isSquashed());
619 
620  load_fault = inst->initiateAcc();
621 
622  if (load_fault == NoFault && !inst->readMemAccPredicate()) {
623  assert(inst->readPredicate());
624  inst->setExecuted();
625  inst->completeAcc(nullptr);
626  iewStage->instToCommit(inst);
627  iewStage->activityThisCycle();
628  return NoFault;
629  }
630 
631  if (inst->isTranslationDelayed() && load_fault == NoFault)
632  return load_fault;
633 
634  if (load_fault != NoFault && inst->translationCompleted() &&
635  inst->savedReq->isPartialFault() && !inst->savedReq->isComplete()) {
636  assert(inst->savedReq->isSplit());
637  // If we have a partial fault where the mem access is not complete yet
638  // then the cache must have been blocked. This load will be re-executed
639  // when the cache gets unblocked. We will handle the fault when the
640  // mem access is complete.
641  return NoFault;
642  }
643 
644  // If the instruction faulted or predicated false, then we need to send it
645  // along to commit without the instruction completing.
646  if (load_fault != NoFault || !inst->readPredicate()) {
647  // Send this instruction to commit, also make sure iew stage
648  // realizes there is activity. Mark it as executed unless it
649  // is a strictly ordered load that needs to hit the head of
650  // commit.
651  if (!inst->readPredicate())
652  inst->forwardOldRegs();
653  DPRINTF(LSQUnit, "Load [sn:%lli] not executed from %s\n",
654  inst->seqNum,
655  (load_fault != NoFault ? "fault" : "predication"));
656  if (!(inst->hasRequest() && inst->strictlyOrdered()) ||
657  inst->isAtCommit()) {
658  inst->setExecuted();
659  }
660  iewStage->instToCommit(inst);
661  iewStage->activityThisCycle();
662  } else {
663  if (inst->effAddrValid()) {
664  auto it = inst->lqIt;
665  ++it;
666 
667  if (checkLoads)
668  return checkViolations(it, inst);
669  }
670  }
671 
672  return load_fault;
673 }
674 
675 template <class Impl>
676 Fault
678 {
679  using namespace TheISA;
680  // Make sure that a store exists.
681  assert(stores != 0);
682 
683  int store_idx = store_inst->sqIdx;
684 
685  DPRINTF(LSQUnit, "Executing store PC %s [sn:%lli]\n",
686  store_inst->pcState(), store_inst->seqNum);
687 
688  assert(!store_inst->isSquashed());
689 
690  // Check the recently completed loads to see if any match this store's
691  // address. If so, then we have a memory ordering violation.
692  typename LoadQueue::iterator loadIt = store_inst->lqIt;
693 
694  Fault store_fault = store_inst->initiateAcc();
695 
696  if (store_inst->isTranslationDelayed() &&
697  store_fault == NoFault)
698  return store_fault;
699 
700  if (!store_inst->readPredicate()) {
701  DPRINTF(LSQUnit, "Store [sn:%lli] not executed from predication\n",
702  store_inst->seqNum);
703  store_inst->forwardOldRegs();
704  return store_fault;
705  }
706 
707  if (storeQueue[store_idx].size() == 0) {
708  DPRINTF(LSQUnit,"Fault on Store PC %s, [sn:%lli], Size = 0\n",
709  store_inst->pcState(), store_inst->seqNum);
710 
711  return store_fault;
712  }
713 
714  assert(store_fault == NoFault);
715 
716  if (store_inst->isStoreConditional() || store_inst->isAtomic()) {
717  // Store conditionals and Atomics need to set themselves as able to
718  // writeback if we haven't had a fault by here.
719  storeQueue[store_idx].canWB() = true;
720 
721  ++storesToWB;
722  }
723 
724  return checkViolations(loadIt, store_inst);
725 
726 }
727 
728 template <class Impl>
729 void
731 {
732  assert(loadQueue.front().valid());
733 
734  DPRINTF(LSQUnit, "Committing head load instruction, PC %s\n",
735  loadQueue.front().instruction()->pcState());
736 
737  loadQueue.front().clear();
739 
740  --loads;
741 }
742 
743 template <class Impl>
744 void
746 {
747  assert(loads == 0 || loadQueue.front().valid());
748 
749  while (loads != 0 && loadQueue.front().instruction()->seqNum
750  <= youngest_inst) {
751  commitLoad();
752  }
753 }
754 
755 template <class Impl>
756 void
758 {
759  assert(stores == 0 || storeQueue.front().valid());
760 
761  /* Forward iterate the store queue (age order). */
762  for (auto& x : storeQueue) {
763  assert(x.valid());
764  // Mark any stores that are now committed and have not yet
765  // been marked as able to write back.
766  if (!x.canWB()) {
767  if (x.instruction()->seqNum > youngest_inst) {
768  break;
769  }
770  DPRINTF(LSQUnit, "Marking store as able to write back, PC "
771  "%s [sn:%lli]\n",
772  x.instruction()->pcState(),
773  x.instruction()->seqNum);
774 
775  x.canWB() = true;
776 
777  ++storesToWB;
778  }
779  }
780 }
781 
782 template <class Impl>
783 void
785 {
786  assert(isStoreBlocked);
787  storeWBIt->request()->sendPacketToCache();
788  if (storeWBIt->request()->isSent()){
789  storePostSend();
790  }
791 }
792 
793 template <class Impl>
794 void
796 {
797  if (isStoreBlocked) {
798  DPRINTF(LSQUnit, "Writing back blocked store\n");
800  }
801 
802  while (storesToWB > 0 &&
804  storeWBIt->valid() &&
805  storeWBIt->canWB() &&
806  ((!needsTSO) || (!storeInFlight)) &&
807  lsq->cachePortAvailable(false)) {
808 
809  if (isStoreBlocked) {
810  DPRINTF(LSQUnit, "Unable to write back any more stores, cache"
811  " is blocked!\n");
812  break;
813  }
814 
815  // Store didn't write any data so no need to write it back to
816  // memory.
817  if (storeWBIt->size() == 0) {
818  /* It is important that the preincrement happens at (or before)
819  * the call, as the the code of completeStore checks
820  * storeWBIt. */
822  continue;
823  }
824 
825  if (storeWBIt->instruction()->isDataPrefetch()) {
826  storeWBIt++;
827  continue;
828  }
829 
830  assert(storeWBIt->hasRequest());
831  assert(!storeWBIt->committed());
832 
833  DynInstPtr inst = storeWBIt->instruction();
834  LSQRequest* req = storeWBIt->request();
835 
836  // Process store conditionals or store release after all previous
837  // stores are completed
838  if ((req->mainRequest()->isLLSC() ||
839  req->mainRequest()->isRelease()) &&
840  (storeWBIt.idx() != storeQueue.head())) {
841  DPRINTF(LSQUnit, "Store idx:%i PC:%s to Addr:%#x "
842  "[sn:%lli] is %s%s and not head of the queue\n",
843  storeWBIt.idx(), inst->pcState(),
844  req->request()->getPaddr(), inst->seqNum,
845  req->mainRequest()->isLLSC() ? "SC" : "",
846  req->mainRequest()->isRelease() ? "/Release" : "");
847  break;
848  }
849 
850  storeWBIt->committed() = true;
851 
852  assert(!inst->memData);
853  inst->memData = new uint8_t[req->_size];
854 
855  if (storeWBIt->isAllZeros())
856  memset(inst->memData, 0, req->_size);
857  else
858  memcpy(inst->memData, storeWBIt->data(), req->_size);
859 
860 
861  if (req->senderState() == nullptr) {
862  SQSenderState *state = new SQSenderState(storeWBIt);
863  state->isLoad = false;
864  state->needWB = false;
865  state->inst = inst;
866 
867  req->senderState(state);
868  if (inst->isStoreConditional() || inst->isAtomic()) {
869  /* Only store conditionals and atomics need a writeback. */
870  state->needWB = true;
871  }
872  }
873  req->buildPackets();
874 
875  DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%s "
876  "to Addr:%#x, data:%#x [sn:%lli]\n",
877  storeWBIt.idx(), inst->pcState(),
878  req->request()->getPaddr(), (int)*(inst->memData),
879  inst->seqNum);
880 
881  // @todo: Remove this SC hack once the memory system handles it.
882  if (inst->isStoreConditional()) {
883  // Disable recording the result temporarily. Writing to
884  // misc regs normally updates the result, but this is not
885  // the desired behavior when handling store conditionals.
886  inst->recordResult(false);
887  bool success = TheISA::handleLockedWrite(inst.get(),
888  req->request(), cacheBlockMask);
889  inst->recordResult(true);
890  req->packetSent();
891 
892  if (!success) {
893  req->complete();
894  // Instantly complete this store.
895  DPRINTF(LSQUnit, "Store conditional [sn:%lli] failed. "
896  "Instantly completing it.\n",
897  inst->seqNum);
898  PacketPtr new_pkt = new Packet(*req->packet());
899  WritebackEvent *wb = new WritebackEvent(inst,
900  new_pkt, this);
901  cpu->schedule(wb, curTick() + 1);
903  if (!storeQueue.empty())
904  storeWBIt++;
905  else
906  storeWBIt = storeQueue.end();
907  continue;
908  }
909  }
910 
911  if (req->request()->isLocalAccess()) {
912  assert(!inst->isStoreConditional());
913  assert(!inst->inHtmTransactionalState());
914  ThreadContext *thread = cpu->tcBase(lsqID);
915  PacketPtr main_pkt = new Packet(req->mainRequest(),
917  main_pkt->dataStatic(inst->memData);
918  req->request()->localAccessor(thread, main_pkt);
919  delete main_pkt;
921  storeWBIt++;
922  continue;
923  }
924  /* Send to cache */
925  req->sendPacketToCache();
926 
927  /* If successful, do the post send */
928  if (req->isSent()) {
929  storePostSend();
930  } else {
931  DPRINTF(LSQUnit, "D-Cache became blocked when writing [sn:%lli], "
932  "will retry later\n",
933  inst->seqNum);
934  }
935  }
936  assert(stores >= 0 && storesToWB >= 0);
937 }
938 
939 template <class Impl>
940 void
941 LSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
942 {
943  DPRINTF(LSQUnit, "Squashing until [sn:%lli]!"
944  "(Loads:%i Stores:%i)\n", squashed_num, loads, stores);
945 
946  while (loads != 0 &&
947  loadQueue.back().instruction()->seqNum > squashed_num) {
948  DPRINTF(LSQUnit,"Load Instruction PC %s squashed, "
949  "[sn:%lli]\n",
950  loadQueue.back().instruction()->pcState(),
951  loadQueue.back().instruction()->seqNum);
952 
953  if (isStalled() && loadQueue.tail() == stallingLoadIdx) {
954  stalled = false;
955  stallingStoreIsn = 0;
956  stallingLoadIdx = 0;
957  }
958 
959  // hardware transactional memory
960  // Squashing instructions can alter the transaction nesting depth
961  // and must be corrected before fetching resumes.
962  if (loadQueue.back().instruction()->isHtmStart())
963  {
964  htmStarts = (--htmStarts < 0) ? 0 : htmStarts;
965  DPRINTF(HtmCpu, ">> htmStarts-- (%d) : htmStops (%d)\n",
967  }
968  if (loadQueue.back().instruction()->isHtmStop())
969  {
970  htmStops = (--htmStops < 0) ? 0 : htmStops;
971  DPRINTF(HtmCpu, ">> htmStarts (%d) : htmStops-- (%d)\n",
973  }
974  // Clear the smart pointer to make sure it is decremented.
975  loadQueue.back().instruction()->setSquashed();
976  loadQueue.back().clear();
977 
978  --loads;
979 
982  }
983 
984  // hardware transactional memory
985  // scan load queue (from oldest to youngest) for most recent valid htmUid
986  auto scan_it = loadQueue.begin();
987  uint64_t in_flight_uid = 0;
988  while (scan_it != loadQueue.end()) {
989  if (scan_it->instruction()->isHtmStart() &&
990  !scan_it->instruction()->isSquashed()) {
991  in_flight_uid = scan_it->instruction()->getHtmTransactionUid();
992  DPRINTF(HtmCpu, "loadQueue[%d]: found valid HtmStart htmUid=%u\n",
993  scan_it._idx, in_flight_uid);
994  }
995  scan_it++;
996  }
997  // If there's a HtmStart in the pipeline then use its htmUid,
998  // otherwise use the most recently committed uid
999  const auto& htm_cpt = cpu->tcBase(lsqID)->getHtmCheckpointPtr();
1000  if (htm_cpt) {
1001  const uint64_t old_local_htm_uid = htm_cpt->getHtmUid();
1002  uint64_t new_local_htm_uid;
1003  if (in_flight_uid > 0)
1004  new_local_htm_uid = in_flight_uid;
1005  else
1006  new_local_htm_uid = lastRetiredHtmUid;
1007 
1008  if (old_local_htm_uid != new_local_htm_uid) {
1009  DPRINTF(HtmCpu, "flush: lastRetiredHtmUid=%u\n",
1011  DPRINTF(HtmCpu, "flush: resetting localHtmUid=%u\n",
1012  new_local_htm_uid);
1013 
1014  htm_cpt->setHtmUid(new_local_htm_uid);
1015  }
1016  }
1017 
1018  if (memDepViolator && squashed_num < memDepViolator->seqNum) {
1019  memDepViolator = NULL;
1020  }
1021 
1022  while (stores != 0 &&
1023  storeQueue.back().instruction()->seqNum > squashed_num) {
1024  // Instructions marked as can WB are already committed.
1025  if (storeQueue.back().canWB()) {
1026  break;
1027  }
1028 
1029  DPRINTF(LSQUnit,"Store Instruction PC %s squashed, "
1030  "idx:%i [sn:%lli]\n",
1031  storeQueue.back().instruction()->pcState(),
1032  storeQueue.tail(), storeQueue.back().instruction()->seqNum);
1033 
1034  // I don't think this can happen. It should have been cleared
1035  // by the stalling load.
1036  if (isStalled() &&
1037  storeQueue.back().instruction()->seqNum == stallingStoreIsn) {
1038  panic("Is stalled should have been cleared by stalling load!\n");
1039  stalled = false;
1040  stallingStoreIsn = 0;
1041  }
1042 
1043  // Clear the smart pointer to make sure it is decremented.
1044  storeQueue.back().instruction()->setSquashed();
1045 
1046  // Must delete request now that it wasn't handed off to
1047  // memory. This is quite ugly. @todo: Figure out the proper
1048  // place to really handle request deletes.
1049  storeQueue.back().clear();
1050  --stores;
1051 
1052  storeQueue.pop_back();
1054  }
1055 }
1056 
1057 template <class Impl>
1058 void
1060 {
1061  if (isStalled() &&
1062  storeWBIt->instruction()->seqNum == stallingStoreIsn) {
1063  DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
1064  "load idx:%i\n",
1066  stalled = false;
1067  stallingStoreIsn = 0;
1068  iewStage->replayMemInst(loadQueue[stallingLoadIdx].instruction());
1069  }
1070 
1071  if (!storeWBIt->instruction()->isStoreConditional()) {
1072  // The store is basically completed at this time. This
1073  // only works so long as the checker doesn't try to
1074  // verify the value in memory for stores.
1075  storeWBIt->instruction()->setCompleted();
1076 
1077  if (cpu->checker) {
1078  cpu->checker->verify(storeWBIt->instruction());
1079  }
1080  }
1081 
1082  if (needsTSO) {
1083  storeInFlight = true;
1084  }
1085 
1086  storeWBIt++;
1087 }
1088 
1089 template <class Impl>
1090 void
1092 {
1093  iewStage->wakeCPU();
1094 
1095  // Squashed instructions do not need to complete their access.
1096  if (inst->isSquashed()) {
1097  assert (!inst->isStore() || inst->isStoreConditional());
1099  return;
1100  }
1101 
1102  if (!inst->isExecuted()) {
1103  inst->setExecuted();
1104 
1105  if (inst->fault == NoFault) {
1106  // Complete access to copy data to proper place.
1107  inst->completeAcc(pkt);
1108  } else {
1109  // If the instruction has an outstanding fault, we cannot complete
1110  // the access as this discards the current fault.
1111 
1112  // If we have an outstanding fault, the fault should only be of
1113  // type ReExec or - in case of a SplitRequest - a partial
1114  // translation fault
1115 
1116  // Unless it's a hardware transactional memory fault
1117  auto htm_fault = std::dynamic_pointer_cast<
1118  GenericHtmFailureFault>(inst->fault);
1119 
1120  if (!htm_fault) {
1121  assert(dynamic_cast<ReExec*>(inst->fault.get()) != nullptr ||
1122  inst->savedReq->isPartialFault());
1123 
1124  } else if (!pkt->htmTransactionFailedInCache()) {
1125  // Situation in which the instruction has a hardware transactional
1126  // memory fault but not the packet itself. This can occur with
1127  // ldp_uop microops since access is spread over multiple packets.
1128  DPRINTF(HtmCpu,
1129  "%s writeback with HTM failure fault, "
1130  "however, completing packet is not aware of "
1131  "transaction failure. cause=%s htmUid=%u\n",
1132  inst->staticInst->getName(),
1133  htmFailureToStr(htm_fault->getHtmFailureFaultCause()),
1134  htm_fault->getHtmUid());
1135  }
1136 
1137  DPRINTF(LSQUnit, "Not completing instruction [sn:%lli] access "
1138  "due to pending fault.\n", inst->seqNum);
1139  }
1140  }
1141 
1142  // Need to insert instruction into queue to commit
1143  iewStage->instToCommit(inst);
1144 
1145  iewStage->activityThisCycle();
1146 
1147  // see if this load changed the PC
1148  iewStage->checkMisprediction(inst);
1149 }
1150 
1151 template <class Impl>
1152 void
1154 {
1155  assert(store_idx->valid());
1156  store_idx->completed() = true;
1157  --storesToWB;
1158  // A bit conservative because a store completion may not free up entries,
1159  // but hopefully avoids two store completions in one cycle from making
1160  // the CPU tick twice.
1161  cpu->wakeCPU();
1162  cpu->activityThisCycle();
1163 
1164  /* We 'need' a copy here because we may clear the entry from the
1165  * store queue. */
1166  DynInstPtr store_inst = store_idx->instruction();
1167  if (store_idx == storeQueue.begin()) {
1168  do {
1169  storeQueue.front().clear();
1170  storeQueue.pop_front();
1171  --stores;
1172  } while (storeQueue.front().completed() &&
1173  !storeQueue.empty());
1174 
1175  iewStage->updateLSQNextCycle = true;
1176  }
1177 
1178  DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head "
1179  "idx:%i\n",
1180  store_inst->seqNum, store_idx.idx() - 1, storeQueue.head() - 1);
1181 
1182 #if TRACING_ON
1183  if (DTRACE(O3PipeView)) {
1184  store_inst->storeTick =
1185  curTick() - store_inst->fetchTick;
1186  }
1187 #endif
1188 
1189  if (isStalled() &&
1190  store_inst->seqNum == stallingStoreIsn) {
1191  DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
1192  "load idx:%i\n",
1194  stalled = false;
1195  stallingStoreIsn = 0;
1196  iewStage->replayMemInst(loadQueue[stallingLoadIdx].instruction());
1197  }
1198 
1199  store_inst->setCompleted();
1200 
1201  if (needsTSO) {
1202  storeInFlight = false;
1203  }
1204 
1205  // Tell the checker we've completed this instruction. Some stores
1206  // may get reported twice to the checker, but the checker can
1207  // handle that case.
1208  // Store conditionals cannot be sent to the checker yet, they have
1209  // to update the misc registers first which should take place
1210  // when they commit
1211  if (cpu->checker && !store_inst->isStoreConditional()) {
1212  cpu->checker->verify(store_inst);
1213  }
1214 }
1215 
1216 template <class Impl>
1217 bool
1219 {
1220  bool ret = true;
1221  bool cache_got_blocked = false;
1222 
1223  auto state = dynamic_cast<LSQSenderState*>(data_pkt->senderState);
1224 
1225  if (!lsq->cacheBlocked() &&
1226  lsq->cachePortAvailable(isLoad)) {
1227  if (!dcachePort->sendTimingReq(data_pkt)) {
1228  ret = false;
1229  cache_got_blocked = true;
1230  }
1231  } else {
1232  ret = false;
1233  }
1234 
1235  if (ret) {
1236  if (!isLoad) {
1237  isStoreBlocked = false;
1238  }
1239  lsq->cachePortBusy(isLoad);
1240  state->outstanding++;
1241  state->request()->packetSent();
1242  } else {
1243  if (cache_got_blocked) {
1244  lsq->cacheBlocked(true);
1246  }
1247  if (!isLoad) {
1248  assert(state->request() == storeWBIt->request());
1249  isStoreBlocked = true;
1250  }
1251  state->request()->packetNotSent();
1252  }
1253  return ret;
1254 }
1255 
1256 template <class Impl>
1257 void
1259 {
1260  if (isStoreBlocked) {
1261  DPRINTF(LSQUnit, "Receiving retry: blocked store\n");
1263  }
1264 }
1265 
1266 template <class Impl>
1267 void
1269 {
1270  cprintf("Load store queue: Dumping instructions.\n");
1271  cprintf("Load queue size: %i\n", loads);
1272  cprintf("Load queue: ");
1273 
1274  for (const auto& e: loadQueue) {
1275  const DynInstPtr &inst(e.instruction());
1276  cprintf("%s.[sn:%llu] ", inst->pcState(), inst->seqNum);
1277  }
1278  cprintf("\n");
1279 
1280  cprintf("Store queue size: %i\n", stores);
1281  cprintf("Store queue: ");
1282 
1283  for (const auto& e: storeQueue) {
1284  const DynInstPtr &inst(e.instruction());
1285  cprintf("%s.[sn:%llu] ", inst->pcState(), inst->seqNum);
1286  }
1287 
1288  cprintf("\n");
1289 }
1290 
1291 template <class Impl>
1292 unsigned int
1294 {
1295  return cpu->cacheLineSize();
1296 }
1297 
1298 #endif//__CPU_O3_LSQ_UNIT_IMPL_HH__
LSQUnit::insertLoad
void insertLoad(const DynInstPtr &load_inst)
Inserts a load instruction.
Definition: lsq_unit_impl.hh:330
LSQUnit::writebackBlockedStore
void writebackBlockedStore()
Try to finish a previously blocked write back attempt.
Definition: lsq_unit_impl.hh:784
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:1268
LSQUnit::commitLoad
void commitLoad()
Commits the head load.
Definition: lsq_unit_impl.hh:730
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:704
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:233
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:754
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:1059
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 vector.
Definition: circular_queue.hh:812
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
TheISA
Definition: decode_cache.hh:37
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:1293
CircularQueue::pop_back
void pop_back()
Circularly decrease the tail pointer.
Definition: circular_queue.hh:678
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:571
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:447
LSQUnit::getMemDepViolator
DynInstPtr getMemDepViolator()
Returns the memory ordering violator.
Definition: lsq_unit_impl.hh:413
DTRACE
#define DTRACE(x)
Definition: debug.hh:146
CircularQueue::begin
iterator begin()
Iterators.
Definition: circular_queue.hh:755
LSQUnit::init
void init(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params, LSQ *lsq_ptr, unsigned id)
Initializes the LSQ unit with the specified number of entries.
Definition: lsq_unit_impl.hh:217
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
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:1091
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:745
CircularQueue::iterator
Iterator to the circular queue.
Definition: circular_queue.hh:155
LSQUnit::numFreeStoreEntries
unsigned numFreeStoreEntries()
Returns the number of free SQ entries.
Definition: lsq_unit_impl.hh:435
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:295
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:744
LSQUnit::completeStore
void completeStore(typename StoreQueue::iterator store_idx)
Completes the store at the specified index.
Definition: lsq_unit_impl.hh:1153
str.hh
MemCmd::WriteReq
@ WriteReq
Definition: packet.hh:85
LSQUnit::LSQUnitStats::blockedByCache
Stats::Scalar blockedByCache
Number of times the LSQ is blocked due to the cache.
Definition: lsq_unit.hh:592
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:613
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:306
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:608
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:62
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:246
LSQ::cachePortAvailable
bool cachePortAvailable(bool is_load) const
Is any store port available to use?
Definition: lsq_impl.hh:196
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:234
ADD_STAT
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition: group.hh:67
Fault
std::shared_ptr< FaultBase > Fault
Definition: types.hh:240
CircularQueue::iterator::idx
size_t idx() const
OutputIterator has no extra requirements.
Definition: circular_queue.hh:510
cpu.hh
LSQ::cachePortBusy
void cachePortBusy(bool is_load)
Another store port is in use.
Definition: lsq_impl.hh:209
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:757
LSQUnit::insert
void insert(const DynInstPtr &inst)
Inserts an instruction.
Definition: lsq_unit_impl.hh:313
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:784
LSQUnit::writebackStores
void writebackStores()
Writes back stores.
Definition: lsq_unit_impl.hh:795
ReExec
Definition: faults.hh:88
LSQUnit::numFreeLoadEntries
unsigned numFreeLoadEntries()
Returns the number of free LQ entries.
Definition: lsq_unit_impl.hh:424
RiscvISA::x
Bitfield< 3 > x
Definition: pagetable.hh:69
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
NoFault
constexpr decltype(nullptr) NoFault
Definition: types.hh:245
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:142
LSQUnit::trySendPacket
bool trySendPacket(bool isLoad, PacketPtr data_pkt)
Attempts to send a packet to the cache.
Definition: lsq_unit_impl.hh:1218
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:663
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:1258
CircularQueue::empty
bool empty() const
Is the queue empty?
Definition: circular_queue.hh:734
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:288
CircularQueue::capacity
size_t capacity() const
Definition: circular_queue.hh:628
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:677
Packet::dataStatic
void dataStatic(T *p)
Set the data pointer to the following value that should not be freed.
Definition: packet.hh:1107
Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:257
Stats::Group
Statistics container.
Definition: group.hh:83
LSQUnit::needsTSO
bool needsTSO
Flag for memory model.
Definition: lsq_unit.hh:563
LSQUnit::insertStore
void insertStore(const DynInstPtr &store_inst)
Inserts a store instruction.
Definition: lsq_unit_impl.hh:392
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
CircularQueue::moduloAdd
static uint32_t moduloAdd(uint32_t op1, uint32_t op2, uint32_t size)
General modular addition.
Definition: circular_queue.hh:107
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:557
LSQ::cacheBlocked
bool cacheBlocked() const
Is D-cache blocked?
Definition: lsq_impl.hh:182
LSQUnit::cacheBlockMask
Addr cacheBlockMask
Address Mask for a cache block (e.g.
Definition: lsq_unit.hh:529
Stats
Definition: statistics.cc:61
LSQUnit::isStoreBlocked
bool isStoreBlocked
Whehter or not a store is blocked due to the memory system.
Definition: lsq_unit.hh:547
LSQUnit::lastRetiredHtmUid
uint64_t lastRetiredHtmUid
Definition: lsq_unit.hh:521
debugfaults.hh
Packet::senderState
SenderState * senderState
This packet's sender state.
Definition: packet.hh:508
LSQUnit::squash
void squash(const InstSeqNum &squashed_num)
Squashes all instructions younger than a specific sequence number.
Definition: lsq_unit_impl.hh:941
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
CircularQueue::tail
uint32_t tail() const
Definition: circular_queue.hh:623
Request::LLSC
@ LLSC
The request is a Load locked/store conditional.
Definition: request.hh:145
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:609
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:528
curTick
Tick curTick()
The current simulated tick.
Definition: core.hh:45

Generated on Wed Sep 30 2020 14:02:09 for gem5 by doxygen 1.8.17