gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
lsq_unit_impl.hh
Go to the documentation of this file.
1 
2 /*
3  * Copyright (c) 2010-2014 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  * Authors: Kevin Lim
43  * Korey Sewell
44  */
45 
46 #ifndef __CPU_O3_LSQ_UNIT_IMPL_HH__
47 #define __CPU_O3_LSQ_UNIT_IMPL_HH__
48 
50 #include "arch/locked_mem.hh"
51 #include "base/str.hh"
52 #include "config/the_isa.hh"
53 #include "cpu/checker/cpu.hh"
54 #include "cpu/o3/lsq.hh"
55 #include "cpu/o3/lsq_unit.hh"
56 #include "debug/Activity.hh"
57 #include "debug/IEW.hh"
58 #include "debug/LSQUnit.hh"
59 #include "debug/O3PipeView.hh"
60 #include "mem/packet.hh"
61 #include "mem/request.hh"
62 
63 template<class Impl>
65  LSQUnit *lsq_ptr)
66  : Event(Default_Pri, AutoDelete),
67  inst(_inst), pkt(_pkt), lsqPtr(lsq_ptr)
68 {
69 }
70 
71 template<class Impl>
72 void
74 {
75  assert(!lsqPtr->cpu->switchedOut());
76 
77  lsqPtr->writeback(inst, pkt);
78 
79  if (pkt->senderState)
80  delete pkt->senderState;
81 
82  delete pkt->req;
83  delete pkt;
84 }
85 
86 template<class Impl>
87 const char *
89 {
90  return "Store writeback";
91 }
92 
93 template<class Impl>
94 void
96 {
97  LSQSenderState *state = dynamic_cast<LSQSenderState *>(pkt->senderState);
98  DynInstPtr inst = state->inst;
99  DPRINTF(IEW, "Writeback event [sn:%lli].\n", inst->seqNum);
100  DPRINTF(Activity, "Activity: Writeback event [sn:%lli].\n", inst->seqNum);
101 
102  if (state->cacheBlocked) {
103  // This is the first half of a previous split load,
104  // where the 2nd half blocked, ignore this response
105  DPRINTF(IEW, "[sn:%lli]: Response from first half of earlier "
106  "blocked split load recieved. Ignoring.\n", inst->seqNum);
107  delete state;
108  return;
109  }
110 
111  // If this is a split access, wait until all packets are received.
112  if (TheISA::HasUnalignedMemAcc && !state->complete()) {
113  return;
114  }
115 
116  assert(!cpu->switchedOut());
117  if (!inst->isSquashed()) {
118  if (!state->noWB) {
119  if (!TheISA::HasUnalignedMemAcc || !state->isSplit ||
120  !state->isLoad) {
121  writeback(inst, pkt);
122  } else {
123  writeback(inst, state->mainPkt);
124  }
125  }
126 
127  if (inst->isStore()) {
128  completeStore(state->idx);
129  }
130  }
131 
132  if (TheISA::HasUnalignedMemAcc && state->isSplit && state->isLoad) {
133  delete state->mainPkt->req;
134  delete state->mainPkt;
135  }
136 
137  pkt->req->setAccessLatency();
138  cpu->ppDataAccessComplete->notify(std::make_pair(inst, pkt));
139 
140  delete state;
141 }
142 
143 template <class Impl>
145  : loads(0), stores(0), storesToWB(0), cacheBlockMask(0), stalled(false),
146  isStoreBlocked(false), storeInFlight(false), hasPendingPkt(false),
147  pendingPkt(nullptr)
148 {
149 }
150 
151 template<class Impl>
152 void
153 LSQUnit<Impl>::init(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params,
154  LSQ *lsq_ptr, unsigned maxLQEntries, unsigned maxSQEntries,
155  unsigned id)
156 {
157  cpu = cpu_ptr;
158  iewStage = iew_ptr;
159 
160  lsq = lsq_ptr;
161 
162  lsqID = id;
163 
164  DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id);
165 
166  // Add 1 for the sentinel entry (they are circular queues).
167  LQEntries = maxLQEntries + 1;
168  SQEntries = maxSQEntries + 1;
169 
170  //Due to uint8_t index in LSQSenderState
171  assert(LQEntries <= 256);
172  assert(SQEntries <= 256);
173 
174  loadQueue.resize(LQEntries);
175  storeQueue.resize(SQEntries);
176 
177  depCheckShift = params->LSQDepCheckShift;
178  checkLoads = params->LSQCheckLoads;
179  cacheStorePorts = params->cacheStorePorts;
180  needsTSO = params->needsTSO;
181 
182  resetState();
183 }
184 
185 
186 template<class Impl>
187 void
189 {
190  loads = stores = storesToWB = 0;
191 
192  loadHead = loadTail = 0;
193 
194  storeHead = storeWBIdx = storeTail = 0;
195 
196  usedStorePorts = 0;
197 
198  retryPkt = NULL;
199  memDepViolator = NULL;
200 
201  stalled = false;
202 
203  cacheBlockMask = ~(cpu->cacheLineSize() - 1);
204 }
205 
206 template<class Impl>
207 std::string
209 {
210  if (Impl::MaxThreads == 1) {
211  return iewStage->name() + ".lsq";
212  } else {
213  return iewStage->name() + ".lsq.thread" + std::to_string(lsqID);
214  }
215 }
216 
217 template<class Impl>
218 void
220 {
221  lsqForwLoads
222  .name(name() + ".forwLoads")
223  .desc("Number of loads that had data forwarded from stores");
224 
225  invAddrLoads
226  .name(name() + ".invAddrLoads")
227  .desc("Number of loads ignored due to an invalid address");
228 
229  lsqSquashedLoads
230  .name(name() + ".squashedLoads")
231  .desc("Number of loads squashed");
232 
233  lsqIgnoredResponses
234  .name(name() + ".ignoredResponses")
235  .desc("Number of memory responses ignored because the instruction is squashed");
236 
237  lsqMemOrderViolation
238  .name(name() + ".memOrderViolation")
239  .desc("Number of memory ordering violations");
240 
241  lsqSquashedStores
242  .name(name() + ".squashedStores")
243  .desc("Number of stores squashed");
244 
245  invAddrSwpfs
246  .name(name() + ".invAddrSwpfs")
247  .desc("Number of software prefetches ignored due to an invalid address");
248 
249  lsqBlockedLoads
250  .name(name() + ".blockedLoads")
251  .desc("Number of blocked loads due to partial load-store forwarding");
252 
253  lsqRescheduledLoads
254  .name(name() + ".rescheduledLoads")
255  .desc("Number of loads that were rescheduled");
256 
257  lsqCacheBlocked
258  .name(name() + ".cacheBlocked")
259  .desc("Number of times an access to memory failed due to the cache being blocked");
260 }
261 
262 template<class Impl>
263 void
265 {
266  dcachePort = dcache_port;
267 }
268 
269 template<class Impl>
270 void
272 {
273  loadQueue.clear();
274 }
275 
276 template<class Impl>
277 void
279 {
280  storeQueue.clear();
281 }
282 
283 template<class Impl>
284 void
286 {
287  for (int i = 0; i < loadQueue.size(); ++i)
288  assert(!loadQueue[i]);
289 
290  assert(storesToWB == 0);
291  assert(!retryPkt);
292 }
293 
294 template<class Impl>
295 void
297 {
298  resetState();
299 }
300 
301 template<class Impl>
302 void
304 {
305  unsigned size_plus_sentinel = size + 1;
306  assert(size_plus_sentinel >= LQEntries);
307 
308  if (size_plus_sentinel > LQEntries) {
309  while (size_plus_sentinel > loadQueue.size()) {
310  DynInstPtr dummy;
311  loadQueue.push_back(dummy);
312  LQEntries++;
313  }
314  } else {
315  LQEntries = size_plus_sentinel;
316  }
317 
318  assert(LQEntries <= 256);
319 }
320 
321 template<class Impl>
322 void
324 {
325  unsigned size_plus_sentinel = size + 1;
326  if (size_plus_sentinel > SQEntries) {
327  while (size_plus_sentinel > storeQueue.size()) {
328  SQEntry dummy;
329  storeQueue.push_back(dummy);
330  SQEntries++;
331  }
332  } else {
333  SQEntries = size_plus_sentinel;
334  }
335 
336  assert(SQEntries <= 256);
337 }
338 
339 template <class Impl>
340 void
342 {
343  assert(inst->isMemRef());
344 
345  assert(inst->isLoad() || inst->isStore());
346 
347  if (inst->isLoad()) {
348  insertLoad(inst);
349  } else {
350  insertStore(inst);
351  }
352 
353  inst->setInLSQ();
354 }
355 
356 template <class Impl>
357 void
359 {
360  assert((loadTail + 1) % LQEntries != loadHead);
361  assert(loads < LQEntries);
362 
363  DPRINTF(LSQUnit, "Inserting load PC %s, idx:%i [sn:%lli]\n",
364  load_inst->pcState(), loadTail, load_inst->seqNum);
365 
366  load_inst->lqIdx = loadTail;
367 
368  if (stores == 0) {
369  load_inst->sqIdx = -1;
370  } else {
371  load_inst->sqIdx = storeTail;
372  }
373 
374  loadQueue[loadTail] = load_inst;
375 
376  incrLdIdx(loadTail);
377 
378  ++loads;
379 }
380 
381 template <class Impl>
382 void
384 {
385  // Make sure it is not full before inserting an instruction.
386  assert((storeTail + 1) % SQEntries != storeHead);
387  assert(stores < SQEntries);
388 
389  DPRINTF(LSQUnit, "Inserting store PC %s, idx:%i [sn:%lli]\n",
390  store_inst->pcState(), storeTail, store_inst->seqNum);
391 
392  store_inst->sqIdx = storeTail;
393  store_inst->lqIdx = loadTail;
394 
395  storeQueue[storeTail] = SQEntry(store_inst);
396 
397  incrStIdx(storeTail);
398 
399  ++stores;
400 }
401 
402 template <class Impl>
403 typename Impl::DynInstPtr
405 {
406  DynInstPtr temp = memDepViolator;
407 
408  memDepViolator = NULL;
409 
410  return temp;
411 }
412 
413 template <class Impl>
414 unsigned
416 {
417  //LQ has an extra dummy entry to differentiate
418  //empty/full conditions. Subtract 1 from the free entries.
419  DPRINTF(LSQUnit, "LQ size: %d, #loads occupied: %d\n", LQEntries, loads);
420  return LQEntries - loads - 1;
421 }
422 
423 template <class Impl>
424 unsigned
426 {
427  //SQ has an extra dummy entry to differentiate
428  //empty/full conditions. Subtract 1 from the free entries.
429  DPRINTF(LSQUnit, "SQ size: %d, #stores occupied: %d\n", SQEntries, stores);
430  return SQEntries - stores - 1;
431 
432  }
433 
434 template <class Impl>
435 void
437 {
438  // Should only ever get invalidations in here
439  assert(pkt->isInvalidate());
440 
441  int load_idx = loadHead;
442  DPRINTF(LSQUnit, "Got snoop for address %#x\n", pkt->getAddr());
443 
444  // Only Invalidate packet calls checkSnoop
445  assert(pkt->isInvalidate());
446  for (int x = 0; x < cpu->numContexts(); x++) {
447  ThreadContext *tc = cpu->getContext(x);
448  bool no_squash = cpu->thread[x]->noSquashFromTC;
449  cpu->thread[x]->noSquashFromTC = true;
450  TheISA::handleLockedSnoop(tc, pkt, cacheBlockMask);
451  cpu->thread[x]->noSquashFromTC = no_squash;
452  }
453 
454  Addr invalidate_addr = pkt->getAddr() & cacheBlockMask;
455 
456  DynInstPtr ld_inst = loadQueue[load_idx];
457  if (ld_inst) {
458  Addr load_addr_low = ld_inst->physEffAddrLow & cacheBlockMask;
459  Addr load_addr_high = ld_inst->physEffAddrHigh & cacheBlockMask;
460 
461  // Check that this snoop didn't just invalidate our lock flag
462  if (ld_inst->effAddrValid() && (load_addr_low == invalidate_addr
463  || load_addr_high == invalidate_addr)
464  && ld_inst->memReqFlags & Request::LLSC)
465  TheISA::handleLockedSnoopHit(ld_inst.get());
466  }
467 
468  // If this is the only load in the LSQ we don't care
469  if (load_idx == loadTail)
470  return;
471 
472  incrLdIdx(load_idx);
473 
474  bool force_squash = false;
475 
476  while (load_idx != loadTail) {
477  DynInstPtr ld_inst = loadQueue[load_idx];
478 
479  if (!ld_inst->effAddrValid() || ld_inst->strictlyOrdered()) {
480  incrLdIdx(load_idx);
481  continue;
482  }
483 
484  Addr load_addr_low = ld_inst->physEffAddrLow & cacheBlockMask;
485  Addr load_addr_high = ld_inst->physEffAddrHigh & cacheBlockMask;
486 
487  DPRINTF(LSQUnit, "-- inst [sn:%lli] load_addr: %#x to pktAddr:%#x\n",
488  ld_inst->seqNum, load_addr_low, invalidate_addr);
489 
490  if ((load_addr_low == invalidate_addr
491  || load_addr_high == invalidate_addr) || force_squash) {
492  if (needsTSO) {
493  // If we have a TSO system, as all loads must be ordered with
494  // all other loads, this load as well as *all* subsequent loads
495  // need to be squashed to prevent possible load reordering.
496  force_squash = true;
497  }
498  if (ld_inst->possibleLoadViolation() || force_squash) {
499  DPRINTF(LSQUnit, "Conflicting load at addr %#x [sn:%lli]\n",
500  pkt->getAddr(), ld_inst->seqNum);
501 
502  // Mark the load for re-execution
503  ld_inst->fault = std::make_shared<ReExec>();
504  } else {
505  DPRINTF(LSQUnit, "HitExternal Snoop for addr %#x [sn:%lli]\n",
506  pkt->getAddr(), ld_inst->seqNum);
507 
508  // Make sure that we don't lose a snoop hitting a LOCKED
509  // address since the LOCK* flags don't get updated until
510  // commit.
511  if (ld_inst->memReqFlags & Request::LLSC)
512  TheISA::handleLockedSnoopHit(ld_inst.get());
513 
514  // If a older load checks this and it's true
515  // then we might have missed the snoop
516  // in which case we need to invalidate to be sure
517  ld_inst->hitExternalSnoop(true);
518  }
519  }
520  incrLdIdx(load_idx);
521  }
522  return;
523 }
524 
525 template <class Impl>
526 Fault
528 {
529  Addr inst_eff_addr1 = inst->effAddr >> depCheckShift;
530  Addr inst_eff_addr2 = (inst->effAddr + inst->effSize - 1) >> depCheckShift;
531 
537  while (load_idx != loadTail) {
538  DynInstPtr ld_inst = loadQueue[load_idx];
539  if (!ld_inst->effAddrValid() || ld_inst->strictlyOrdered()) {
540  incrLdIdx(load_idx);
541  continue;
542  }
543 
544  Addr ld_eff_addr1 = ld_inst->effAddr >> depCheckShift;
545  Addr ld_eff_addr2 =
546  (ld_inst->effAddr + ld_inst->effSize - 1) >> depCheckShift;
547 
548  if (inst_eff_addr2 >= ld_eff_addr1 && inst_eff_addr1 <= ld_eff_addr2) {
549  if (inst->isLoad()) {
550  // If this load is to the same block as an external snoop
551  // invalidate that we've observed then the load needs to be
552  // squashed as it could have newer data
553  if (ld_inst->hitExternalSnoop()) {
554  if (!memDepViolator ||
555  ld_inst->seqNum < memDepViolator->seqNum) {
556  DPRINTF(LSQUnit, "Detected fault with inst [sn:%lli] "
557  "and [sn:%lli] at address %#x\n",
558  inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
559  memDepViolator = ld_inst;
560 
561  ++lsqMemOrderViolation;
562 
563  return std::make_shared<GenericISA::M5PanicFault>(
564  "Detected fault with inst [sn:%lli] and "
565  "[sn:%lli] at address %#x\n",
566  inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
567  }
568  }
569 
570  // Otherwise, mark the load has a possible load violation
571  // and if we see a snoop before it's commited, we need to squash
572  ld_inst->possibleLoadViolation(true);
573  DPRINTF(LSQUnit, "Found possible load violation at addr: %#x"
574  " between instructions [sn:%lli] and [sn:%lli]\n",
575  inst_eff_addr1, inst->seqNum, ld_inst->seqNum);
576  } else {
577  // A load/store incorrectly passed this store.
578  // Check if we already have a violator, or if it's newer
579  // squash and refetch.
580  if (memDepViolator && ld_inst->seqNum > memDepViolator->seqNum)
581  break;
582 
583  DPRINTF(LSQUnit, "Detected fault with inst [sn:%lli] and "
584  "[sn:%lli] at address %#x\n",
585  inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
586  memDepViolator = ld_inst;
587 
588  ++lsqMemOrderViolation;
589 
590  return std::make_shared<GenericISA::M5PanicFault>(
591  "Detected fault with "
592  "inst [sn:%lli] and [sn:%lli] at address %#x\n",
593  inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
594  }
595  }
596 
597  incrLdIdx(load_idx);
598  }
599  return NoFault;
600 }
601 
602 
603 
604 
605 template <class Impl>
606 Fault
608 {
609  using namespace TheISA;
610  // Execute a specific load.
611  Fault load_fault = NoFault;
612 
613  DPRINTF(LSQUnit, "Executing load PC %s, [sn:%lli]\n",
614  inst->pcState(), inst->seqNum);
615 
616  assert(!inst->isSquashed());
617 
618  load_fault = inst->initiateAcc();
619 
620  if (inst->isTranslationDelayed() &&
621  load_fault == NoFault)
622  return load_fault;
623 
624  // If the instruction faulted or predicated false, then we need to send it
625  // along to commit without the instruction completing.
626  if (load_fault != NoFault || !inst->readPredicate()) {
627  // Send this instruction to commit, also make sure iew stage
628  // realizes there is activity. Mark it as executed unless it
629  // is a strictly ordered load that needs to hit the head of
630  // commit.
631  if (!inst->readPredicate())
632  inst->forwardOldRegs();
633  DPRINTF(LSQUnit, "Load [sn:%lli] not executed from %s\n",
634  inst->seqNum,
635  (load_fault != NoFault ? "fault" : "predication"));
636  if (!(inst->hasRequest() && inst->strictlyOrdered()) ||
637  inst->isAtCommit()) {
638  inst->setExecuted();
639  }
640  iewStage->instToCommit(inst);
641  iewStage->activityThisCycle();
642  } else {
643  assert(inst->effAddrValid());
644  int load_idx = inst->lqIdx;
645  incrLdIdx(load_idx);
646 
647  if (checkLoads)
648  return checkViolations(load_idx, inst);
649  }
650 
651  return load_fault;
652 }
653 
654 template <class Impl>
655 Fault
657 {
658  using namespace TheISA;
659  // Make sure that a store exists.
660  assert(stores != 0);
661 
662  int store_idx = store_inst->sqIdx;
663 
664  DPRINTF(LSQUnit, "Executing store PC %s [sn:%lli]\n",
665  store_inst->pcState(), store_inst->seqNum);
666 
667  assert(!store_inst->isSquashed());
668 
669  // Check the recently completed loads to see if any match this store's
670  // address. If so, then we have a memory ordering violation.
671  int load_idx = store_inst->lqIdx;
672 
673  Fault store_fault = store_inst->initiateAcc();
674 
675  if (store_inst->isTranslationDelayed() &&
676  store_fault == NoFault)
677  return store_fault;
678 
679  if (!store_inst->readPredicate())
680  store_inst->forwardOldRegs();
681 
682  if (storeQueue[store_idx].size == 0) {
683  DPRINTF(LSQUnit,"Fault on Store PC %s, [sn:%lli], Size = 0\n",
684  store_inst->pcState(), store_inst->seqNum);
685 
686  return store_fault;
687  } else if (!store_inst->readPredicate()) {
688  DPRINTF(LSQUnit, "Store [sn:%lli] not executed from predication\n",
689  store_inst->seqNum);
690  return store_fault;
691  }
692 
693  assert(store_fault == NoFault);
694 
695  if (store_inst->isStoreConditional()) {
696  // Store conditionals need to set themselves as able to
697  // writeback if we haven't had a fault by here.
698  storeQueue[store_idx].canWB = true;
699 
700  ++storesToWB;
701  }
702 
703  return checkViolations(load_idx, store_inst);
704 
705 }
706 
707 template <class Impl>
708 void
710 {
711  assert(loadQueue[loadHead]);
712 
713  DPRINTF(LSQUnit, "Committing head load instruction, PC %s\n",
714  loadQueue[loadHead]->pcState());
715 
716  loadQueue[loadHead] = NULL;
717 
718  incrLdIdx(loadHead);
719 
720  --loads;
721 }
722 
723 template <class Impl>
724 void
726 {
727  assert(loads == 0 || loadQueue[loadHead]);
728 
729  while (loads != 0 && loadQueue[loadHead]->seqNum <= youngest_inst) {
730  commitLoad();
731  }
732 }
733 
734 template <class Impl>
735 void
737 {
738  assert(stores == 0 || storeQueue[storeHead].inst);
739 
740  int store_idx = storeHead;
741 
742  while (store_idx != storeTail) {
743  assert(storeQueue[store_idx].inst);
744  // Mark any stores that are now committed and have not yet
745  // been marked as able to write back.
746  if (!storeQueue[store_idx].canWB) {
747  if (storeQueue[store_idx].inst->seqNum > youngest_inst) {
748  break;
749  }
750  DPRINTF(LSQUnit, "Marking store as able to write back, PC "
751  "%s [sn:%lli]\n",
752  storeQueue[store_idx].inst->pcState(),
753  storeQueue[store_idx].inst->seqNum);
754 
755  storeQueue[store_idx].canWB = true;
756 
757  ++storesToWB;
758  }
759 
760  incrStIdx(store_idx);
761  }
762 }
763 
764 template <class Impl>
765 void
767 {
768  if (hasPendingPkt) {
769  assert(pendingPkt != NULL);
770 
771  // If the cache is blocked, this will store the packet for retry.
772  if (sendStore(pendingPkt)) {
773  storePostSend(pendingPkt);
774  }
775  pendingPkt = NULL;
776  hasPendingPkt = false;
777  }
778 }
779 
780 template <class Impl>
781 void
783 {
784  // First writeback the second packet from any split store that didn't
785  // complete last cycle because there weren't enough cache ports available.
787  writebackPendingStore();
788  }
789 
790  while (storesToWB > 0 &&
791  storeWBIdx != storeTail &&
792  storeQueue[storeWBIdx].inst &&
793  storeQueue[storeWBIdx].canWB &&
794  ((!needsTSO) || (!storeInFlight)) &&
795  usedStorePorts < cacheStorePorts) {
796 
797  if (isStoreBlocked) {
798  DPRINTF(LSQUnit, "Unable to write back any more stores, cache"
799  " is blocked!\n");
800  break;
801  }
802 
803  // Store didn't write any data so no need to write it back to
804  // memory.
805  if (storeQueue[storeWBIdx].size == 0) {
806  completeStore(storeWBIdx);
807 
808  incrStIdx(storeWBIdx);
809 
810  continue;
811  }
812 
813  ++usedStorePorts;
814 
815  if (storeQueue[storeWBIdx].inst->isDataPrefetch()) {
816  incrStIdx(storeWBIdx);
817 
818  continue;
819  }
820 
821  assert(storeQueue[storeWBIdx].req);
822  assert(!storeQueue[storeWBIdx].committed);
823 
824  if (TheISA::HasUnalignedMemAcc && storeQueue[storeWBIdx].isSplit) {
825  assert(storeQueue[storeWBIdx].sreqLow);
826  assert(storeQueue[storeWBIdx].sreqHigh);
827  }
828 
829  DynInstPtr inst = storeQueue[storeWBIdx].inst;
830 
831  Request *req = storeQueue[storeWBIdx].req;
832  RequestPtr sreqLow = storeQueue[storeWBIdx].sreqLow;
833  RequestPtr sreqHigh = storeQueue[storeWBIdx].sreqHigh;
834 
835  storeQueue[storeWBIdx].committed = true;
836 
837  assert(!inst->memData);
838  inst->memData = new uint8_t[req->getSize()];
839 
840  if (storeQueue[storeWBIdx].isAllZeros)
841  memset(inst->memData, 0, req->getSize());
842  else
843  memcpy(inst->memData, storeQueue[storeWBIdx].data, req->getSize());
844 
845  PacketPtr data_pkt;
846  PacketPtr snd_data_pkt = NULL;
847 
848  LSQSenderState *state = new LSQSenderState;
849  state->isLoad = false;
850  state->idx = storeWBIdx;
851  state->inst = inst;
852 
853  if (!TheISA::HasUnalignedMemAcc || !storeQueue[storeWBIdx].isSplit) {
854 
855  // Build a single data packet if the store isn't split.
856  data_pkt = Packet::createWrite(req);
857  data_pkt->dataStatic(inst->memData);
858  data_pkt->senderState = state;
859  } else {
860  // Create two packets if the store is split in two.
861  data_pkt = Packet::createWrite(sreqLow);
862  snd_data_pkt = Packet::createWrite(sreqHigh);
863 
864  data_pkt->dataStatic(inst->memData);
865  snd_data_pkt->dataStatic(inst->memData + sreqLow->getSize());
866 
867  data_pkt->senderState = state;
868  snd_data_pkt->senderState = state;
869 
870  state->isSplit = true;
871  state->outstanding = 2;
872 
873  // Can delete the main request now.
874  delete req;
875  req = sreqLow;
876  }
877 
878  DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%s "
879  "to Addr:%#x, data:%#x [sn:%lli]\n",
880  storeWBIdx, inst->pcState(),
881  req->getPaddr(), (int)*(inst->memData),
882  inst->seqNum);
883 
884  // @todo: Remove this SC hack once the memory system handles it.
885  if (inst->isStoreConditional()) {
886  assert(!storeQueue[storeWBIdx].isSplit);
887  // Disable recording the result temporarily. Writing to
888  // misc regs normally updates the result, but this is not
889  // the desired behavior when handling store conditionals.
890  inst->recordResult(false);
891  bool success = TheISA::handleLockedWrite(inst.get(), req, cacheBlockMask);
892  inst->recordResult(true);
893 
894  if (!success) {
895  // Instantly complete this store.
896  DPRINTF(LSQUnit, "Store conditional [sn:%lli] failed. "
897  "Instantly completing it.\n",
898  inst->seqNum);
899  WritebackEvent *wb = new WritebackEvent(inst, data_pkt, this);
900  cpu->schedule(wb, curTick() + 1);
901  if (cpu->checker) {
902  // Make sure to set the LLSC data for verification
903  // if checker is loaded
904  inst->reqToVerify->setExtraData(0);
905  inst->completeAcc(data_pkt);
906  }
907  completeStore(storeWBIdx);
908  incrStIdx(storeWBIdx);
909  continue;
910  }
911  } else {
912  // Non-store conditionals do not need a writeback.
913  state->noWB = true;
914  }
915 
916  bool split =
917  TheISA::HasUnalignedMemAcc && storeQueue[storeWBIdx].isSplit;
918 
919  ThreadContext *thread = cpu->tcBase(lsqID);
920 
921  if (req->isMmappedIpr()) {
922  assert(!inst->isStoreConditional());
923  TheISA::handleIprWrite(thread, data_pkt);
924  delete data_pkt;
925  if (split) {
926  assert(snd_data_pkt->req->isMmappedIpr());
927  TheISA::handleIprWrite(thread, snd_data_pkt);
928  delete snd_data_pkt;
929  delete sreqLow;
930  delete sreqHigh;
931  }
932  delete state;
933  delete req;
934  completeStore(storeWBIdx);
935  incrStIdx(storeWBIdx);
936  } else if (!sendStore(data_pkt)) {
937  DPRINTF(IEW, "D-Cache became blocked when writing [sn:%lli], will"
938  "retry later\n",
939  inst->seqNum);
940 
941  // Need to store the second packet, if split.
942  if (split) {
943  state->pktToSend = true;
944  state->pendingPacket = snd_data_pkt;
945  }
946  } else {
947 
948  // If split, try to send the second packet too
949  if (split) {
950  assert(snd_data_pkt);
951 
952  // Ensure there are enough ports to use.
953  if (usedStorePorts < cacheStorePorts) {
954  ++usedStorePorts;
955  if (sendStore(snd_data_pkt)) {
956  storePostSend(snd_data_pkt);
957  } else {
958  DPRINTF(IEW, "D-Cache became blocked when writing"
959  " [sn:%lli] second packet, will retry later\n",
960  inst->seqNum);
961  }
962  } else {
963 
964  // Store the packet for when there's free ports.
965  assert(pendingPkt == NULL);
966  pendingPkt = snd_data_pkt;
967  hasPendingPkt = true;
968  }
969  } else {
970 
971  // Not a split store.
972  storePostSend(data_pkt);
973  }
974  }
975  }
976 
977  // Not sure this should set it to 0.
978  usedStorePorts = 0;
979 
980  assert(stores >= 0 && storesToWB >= 0);
981 }
982 
983 /*template <class Impl>
984 void
985 LSQUnit<Impl>::removeMSHR(InstSeqNum seqNum)
986 {
987  list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(),
988  mshrSeqNums.end(),
989  seqNum);
990 
991  if (mshr_it != mshrSeqNums.end()) {
992  mshrSeqNums.erase(mshr_it);
993  DPRINTF(LSQUnit, "Removing MSHR. count = %i\n",mshrSeqNums.size());
994  }
995 }*/
996 
997 template <class Impl>
998 void
999 LSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
1000 {
1001  DPRINTF(LSQUnit, "Squashing until [sn:%lli]!"
1002  "(Loads:%i Stores:%i)\n", squashed_num, loads, stores);
1003 
1004  int load_idx = loadTail;
1005  decrLdIdx(load_idx);
1006 
1007  while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) {
1008  DPRINTF(LSQUnit,"Load Instruction PC %s squashed, "
1009  "[sn:%lli]\n",
1010  loadQueue[load_idx]->pcState(),
1011  loadQueue[load_idx]->seqNum);
1012 
1013  if (isStalled() && load_idx == stallingLoadIdx) {
1014  stalled = false;
1015  stallingStoreIsn = 0;
1016  stallingLoadIdx = 0;
1017  }
1018 
1019  // Clear the smart pointer to make sure it is decremented.
1020  loadQueue[load_idx]->setSquashed();
1021  loadQueue[load_idx] = NULL;
1022  --loads;
1023 
1024  // Inefficient!
1025  loadTail = load_idx;
1026 
1027  decrLdIdx(load_idx);
1028  ++lsqSquashedLoads;
1029  }
1030 
1031  if (memDepViolator && squashed_num < memDepViolator->seqNum) {
1032  memDepViolator = NULL;
1033  }
1034 
1035  int store_idx = storeTail;
1036  decrStIdx(store_idx);
1037 
1038  while (stores != 0 &&
1039  storeQueue[store_idx].inst->seqNum > squashed_num) {
1040  // Instructions marked as can WB are already committed.
1041  if (storeQueue[store_idx].canWB) {
1042  break;
1043  }
1044 
1045  DPRINTF(LSQUnit,"Store Instruction PC %s squashed, "
1046  "idx:%i [sn:%lli]\n",
1047  storeQueue[store_idx].inst->pcState(),
1048  store_idx, storeQueue[store_idx].inst->seqNum);
1049 
1050  // I don't think this can happen. It should have been cleared
1051  // by the stalling load.
1052  if (isStalled() &&
1053  storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
1054  panic("Is stalled should have been cleared by stalling load!\n");
1055  stalled = false;
1056  stallingStoreIsn = 0;
1057  }
1058 
1059  // Clear the smart pointer to make sure it is decremented.
1060  storeQueue[store_idx].inst->setSquashed();
1061  storeQueue[store_idx].inst = NULL;
1062  storeQueue[store_idx].canWB = 0;
1063 
1064  // Must delete request now that it wasn't handed off to
1065  // memory. This is quite ugly. @todo: Figure out the proper
1066  // place to really handle request deletes.
1067  delete storeQueue[store_idx].req;
1068  if (TheISA::HasUnalignedMemAcc && storeQueue[store_idx].isSplit) {
1069  delete storeQueue[store_idx].sreqLow;
1070  delete storeQueue[store_idx].sreqHigh;
1071 
1072  storeQueue[store_idx].sreqLow = NULL;
1073  storeQueue[store_idx].sreqHigh = NULL;
1074  }
1075 
1076  storeQueue[store_idx].req = NULL;
1077  --stores;
1078 
1079  // Inefficient!
1080  storeTail = store_idx;
1081 
1082  decrStIdx(store_idx);
1083  ++lsqSquashedStores;
1084  }
1085 }
1086 
1087 template <class Impl>
1088 void
1090 {
1091  if (isStalled() &&
1092  storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) {
1093  DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
1094  "load idx:%i\n",
1095  stallingStoreIsn, stallingLoadIdx);
1096  stalled = false;
1097  stallingStoreIsn = 0;
1098  iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
1099  }
1100 
1101  if (!storeQueue[storeWBIdx].inst->isStoreConditional()) {
1102  // The store is basically completed at this time. This
1103  // only works so long as the checker doesn't try to
1104  // verify the value in memory for stores.
1105  storeQueue[storeWBIdx].inst->setCompleted();
1106 
1107  if (cpu->checker) {
1108  cpu->checker->verify(storeQueue[storeWBIdx].inst);
1109  }
1110  }
1111 
1112  if (needsTSO) {
1113  storeInFlight = true;
1114  }
1115 
1116  incrStIdx(storeWBIdx);
1117 }
1118 
1119 template <class Impl>
1120 void
1122 {
1123  iewStage->wakeCPU();
1124 
1125  // Squashed instructions do not need to complete their access.
1126  if (inst->isSquashed()) {
1127  assert(!inst->isStore());
1128  ++lsqIgnoredResponses;
1129  return;
1130  }
1131 
1132  if (!inst->isExecuted()) {
1133  inst->setExecuted();
1134 
1135  if (inst->fault == NoFault) {
1136  // Complete access to copy data to proper place.
1137  inst->completeAcc(pkt);
1138  } else {
1139  // If the instruction has an outstanding fault, we cannot complete
1140  // the access as this discards the current fault.
1141 
1142  // If we have an outstanding fault, the fault should only be of
1143  // type ReExec.
1144  assert(dynamic_cast<ReExec*>(inst->fault.get()) != nullptr);
1145 
1146  DPRINTF(LSQUnit, "Not completing instruction [sn:%lli] access "
1147  "due to pending fault.\n", inst->seqNum);
1148  }
1149  }
1150 
1151  // Need to insert instruction into queue to commit
1152  iewStage->instToCommit(inst);
1153 
1154  iewStage->activityThisCycle();
1155 
1156  // see if this load changed the PC
1157  iewStage->checkMisprediction(inst);
1158 }
1159 
1160 template <class Impl>
1161 void
1163 {
1164  assert(storeQueue[store_idx].inst);
1165  storeQueue[store_idx].completed = true;
1166  --storesToWB;
1167  // A bit conservative because a store completion may not free up entries,
1168  // but hopefully avoids two store completions in one cycle from making
1169  // the CPU tick twice.
1170  cpu->wakeCPU();
1171  cpu->activityThisCycle();
1172 
1173  if (store_idx == storeHead) {
1174  do {
1175  incrStIdx(storeHead);
1176 
1177  --stores;
1178  } while (storeQueue[storeHead].completed &&
1179  storeHead != storeTail);
1180 
1181  iewStage->updateLSQNextCycle = true;
1182  }
1183 
1184  DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head "
1185  "idx:%i\n",
1186  storeQueue[store_idx].inst->seqNum, store_idx, storeHead);
1187 
1188 #if TRACING_ON
1189  if (DTRACE(O3PipeView)) {
1190  storeQueue[store_idx].inst->storeTick =
1191  curTick() - storeQueue[store_idx].inst->fetchTick;
1192  }
1193 #endif
1194 
1195  if (isStalled() &&
1196  storeQueue[store_idx].inst->seqNum == stallingStoreIsn) {
1197  DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] "
1198  "load idx:%i\n",
1199  stallingStoreIsn, stallingLoadIdx);
1200  stalled = false;
1201  stallingStoreIsn = 0;
1202  iewStage->replayMemInst(loadQueue[stallingLoadIdx]);
1203  }
1204 
1205  storeQueue[store_idx].inst->setCompleted();
1206 
1207  if (needsTSO) {
1208  storeInFlight = false;
1209  }
1210 
1211  // Tell the checker we've completed this instruction. Some stores
1212  // may get reported twice to the checker, but the checker can
1213  // handle that case.
1214  if (cpu->checker) {
1215  cpu->checker->verify(storeQueue[store_idx].inst);
1216  }
1217 }
1218 
1219 template <class Impl>
1220 bool
1222 {
1223  if (!dcachePort->sendTimingReq(data_pkt)) {
1224  // Need to handle becoming blocked on a store.
1225  isStoreBlocked = true;
1226  ++lsqCacheBlocked;
1227  assert(retryPkt == NULL);
1228  retryPkt = data_pkt;
1229  return false;
1230  }
1231  return true;
1232 }
1233 
1234 template <class Impl>
1235 void
1237 {
1238  if (isStoreBlocked) {
1239  DPRINTF(LSQUnit, "Receiving retry: store blocked\n");
1240  assert(retryPkt != NULL);
1241 
1242  LSQSenderState *state =
1243  dynamic_cast<LSQSenderState *>(retryPkt->senderState);
1244 
1245  if (dcachePort->sendTimingReq(retryPkt)) {
1246  // Don't finish the store unless this is the last packet.
1247  if (!TheISA::HasUnalignedMemAcc || !state->pktToSend ||
1248  state->pendingPacket == retryPkt) {
1249  state->pktToSend = false;
1250  storePostSend(retryPkt);
1251  }
1252  retryPkt = NULL;
1253  isStoreBlocked = false;
1254 
1255  // Send any outstanding packet.
1256  if (TheISA::HasUnalignedMemAcc && state->pktToSend) {
1257  assert(state->pendingPacket);
1258  if (sendStore(state->pendingPacket)) {
1259  storePostSend(state->pendingPacket);
1260  }
1261  }
1262  } else {
1263  // Still blocked!
1264  ++lsqCacheBlocked;
1265  }
1266  }
1267 }
1268 
1269 template <class Impl>
1270 inline void
1271 LSQUnit<Impl>::incrStIdx(int &store_idx) const
1272 {
1273  if (++store_idx >= SQEntries)
1274  store_idx = 0;
1275 }
1276 
1277 template <class Impl>
1278 inline void
1279 LSQUnit<Impl>::decrStIdx(int &store_idx) const
1280 {
1281  if (--store_idx < 0)
1282  store_idx += SQEntries;
1283 }
1284 
1285 template <class Impl>
1286 inline void
1287 LSQUnit<Impl>::incrLdIdx(int &load_idx) const
1288 {
1289  if (++load_idx >= LQEntries)
1290  load_idx = 0;
1291 }
1292 
1293 template <class Impl>
1294 inline void
1295 LSQUnit<Impl>::decrLdIdx(int &load_idx) const
1296 {
1297  if (--load_idx < 0)
1298  load_idx += LQEntries;
1299 }
1300 
1301 template <class Impl>
1302 void
1304 {
1305  cprintf("Load store queue: Dumping instructions.\n");
1306  cprintf("Load queue size: %i\n", loads);
1307  cprintf("Load queue: ");
1308 
1309  int load_idx = loadHead;
1310 
1311  while (load_idx != loadTail && loadQueue[load_idx]) {
1312  const DynInstPtr &inst(loadQueue[load_idx]);
1313  cprintf("%s.[sn:%i] ", inst->pcState(), inst->seqNum);
1314 
1315  incrLdIdx(load_idx);
1316  }
1317  cprintf("\n");
1318 
1319  cprintf("Store queue size: %i\n", stores);
1320  cprintf("Store queue: ");
1321 
1322  int store_idx = storeHead;
1323 
1324  while (store_idx != storeTail && storeQueue[store_idx].inst) {
1325  const DynInstPtr &inst(storeQueue[store_idx].inst);
1326  cprintf("%s.[sn:%i] ", inst->pcState(), inst->seqNum);
1327 
1328  incrStIdx(store_idx);
1329  }
1330 
1331  cprintf("\n");
1332 }
1333 
1334 #endif//__CPU_O3_LSQ_UNIT_IMPL_HH__
A MasterPort is a specialisation of a BaseMasterPort, which implements the default protocol for the t...
Definition: port.hh:167
#define DPRINTF(x,...)
Definition: trace.hh:212
unsigned numFreeLoadEntries()
Returns the number of free LQ entries.
void squash(const InstSeqNum &squashed_num)
Squashes all instructions younger than a specific sequence number.
Impl::DynInstPtr DynInstPtr
Definition: lsq_unit.hh:82
Fault checkViolations(int load_idx, DynInstPtr &inst)
Check for ordering violations in the LSQ.
decltype(nullptr) constexpr NoFault
Definition: types.hh:189
void resizeSQ(unsigned size)
Resizes the SQ to a given size.
uint8_t idx
The LQ/SQ index of the instruction.
Definition: lsq_unit.hh:294
const std::string & name()
Definition: trace.cc:49
Bitfield< 7 > i
Definition: miscregs.hh:1378
bool isStoreBlocked
Whehter or not a store is blocked due to the memory system.
Definition: lsq_unit.hh:459
WritebackEvent(DynInstPtr &_inst, PacketPtr pkt, LSQUnit *lsq_ptr)
Constructs a writeback event.
#define panic(...)
Definition: misc.hh:153
void drainSanityCheck() const
Perform sanity checks after a drain.
DynInstPtr getMemDepViolator()
Returns the memory ordering violator.
void decrStIdx(int &store_idx) const
Decrements the given store index (circular queue).
void completeStore(int store_idx)
Completes the store at the specified index.
Writeback event, specifically for when stores forward data to loads.
Definition: lsq_unit.hh:313
Declaration of a request, the overall memory request consisting of the parts of the request that are ...
const bool HasUnalignedMemAcc
Definition: isa_traits.hh:119
bool isMmappedIpr() const
Definition: request.hh:776
bool handleLockedWrite(XC *xc, Request *req, Addr cacheBlockMask)
Definition: locked_mem.hh:102
void resetState()
Reset the LSQ state.
Derived class to hold any sender state the LSQ needs.
Definition: lsq_unit.hh:277
void writebackPendingStore()
Writes back a store that couldn't be completed the previous cycle.
void resizeLQ(unsigned size)
Resizes the LQ to a given size.
void regStats()
Registers statistics.
Definition: lsq.hh:58
Cycles handleIprWrite(ThreadContext *xc, Packet *pkt)
Helper function to handle IPRs when the target architecture doesn't need its own IPR handling...
Definition: mmapped_ipr.hh:160
ThreadContext is the external interface to all thread state for anything outside of the CPU...
void insertLoad(DynInstPtr &load_inst)
Inserts a load instruction.
void recvRetry()
Handles doing the retry.
void setAccessLatency()
Set/Get the time taken to complete this request's access, not including the time to successfully tran...
Definition: request.hh:738
void dataStatic(T *p)
Set the data pointer to the following value that should not be freed.
Definition: packet.hh:909
void takeOverFrom()
Takes over from another CPU's thread.
void commitStores(InstSeqNum &youngest_inst)
Commits stores older than a specific sequence number.
std::string name() const
Returns the name of the LSQ unit.
void decrLdIdx(int &load_idx) const
Decrements the given load index (circular queue).
void handleLockedSnoop(XC *xc, PacketPtr pkt, Addr cacheBlockMask)
Definition: locked_mem.hh:69
bool cacheBlocked
Whether or not the second packet of this split load was blocked.
Definition: lsq_unit.hh:306
void init(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params, LSQ *lsq_ptr, unsigned maxLQEntries, unsigned maxSQEntries, unsigned id)
Initializes the LSQ unit with the specified number of entries.
bool hasPendingPkt
Whether or not there is a packet that couldn't be sent because of a lack of cache ports...
Definition: lsq_unit.hh:469
bool storeInFlight
Whether or not a store is in flight.
Definition: lsq_unit.hh:462
void incrLdIdx(int &load_idx) const
Increments the given load index (circular queue).
Tick curTick()
The current simulated tick.
Definition: core.hh:47
bool noWB
Whether or not the instruction will need to writeback.
Definition: lsq_unit.hh:300
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...
#define DTRACE(x)
Definition: trace.hh:210
bool pktToSend
Whether or not there is a packet that needs sending.
Definition: lsq_unit.hh:304
void dumpInsts() const
Debugging function to dump instructions in the LSQ.
void storePostSend(PacketPtr pkt)
Handles completing the send of a store to memory.
bool stalled
Whether or not the LSQ is stalled.
Definition: lsq_unit.hh:447
void commitLoads(InstSeqNum &youngest_inst)
Commits loads older than a specific sequence number.
bool isLoad
Whether or not it is a load.
Definition: lsq_unit.hh:298
bool complete()
Completes a packet and returns whether the access is finished.
Definition: lsq_unit.hh:309
Addr getPaddr() const
Definition: request.hh:519
const RequestPtr req
A pointer to the original request.
Definition: packet.hh:304
void commitLoad()
Commits the head load.
void insert(DynInstPtr &inst)
Inserts an instruction.
void completeDataAccess(PacketPtr pkt)
Completes the data access that has been returned from the memory system.
uint64_t InstSeqNum
Definition: inst_seq.hh:40
LSQUnit()
Constructs an LSQ unit.
void setDcachePort(MasterPort *dcache_port)
Sets the pointer to the dcache port.
PacketPtr pendingPkt
The packet that is pending free cache ports.
Definition: lsq_unit.hh:472
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
bool isSplit
Whether or not this access is split in two.
Definition: lsq_unit.hh:302
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:245
Fault executeLoad(DynInstPtr &inst)
Executes a load instruction.
void clearSQ()
Clears all the entries in the SQ.
Fault executeStore(DynInstPtr &inst)
Executes a store instruction.
int stores
The number of store instructions in the SQ.
Definition: lsq_unit.hh:413
void incrStIdx(int &store_idx) const
Increments the given store index (circular queue).
int size()
Definition: pagetable.hh:146
Declaration of the Packet class.
unsigned numFreeStoreEntries()
Returns the number of free SQ entries.
SenderState * senderState
This packet's sender state.
Definition: packet.hh:454
Definition: eventq.hh:185
void process()
Processes the writeback event.
int storesToWB
The number of store instructions in the SQ waiting to writeback.
Definition: lsq_unit.hh:415
void writebackStores()
Writes back stores.
bool sendStore(PacketPtr data_pkt)
Attempts to send a store to the cache.
PacketPtr pendingPacket
A second packet from a split store that needs sending.
Definition: lsq_unit.hh:292
int loads
The number of load instructions in the LQ.
Definition: lsq_unit.hh:411
O3CPU * cpu
Pointer to the CPU.
Definition: lsq_unit.hh:265
void insertStore(DynInstPtr &store_inst)
Inserts a store instruction.
PacketPtr mainPkt
The main packet from a split load, used during writeback.
Definition: lsq_unit.hh:290
const char * description() const
Returns the description of this event.
void clearLQ()
Clears all the entries in the LQ.
Bitfield< 11 > id
Definition: miscregs.hh:124
uint8_t outstanding
Number of outstanding packets to complete.
Definition: lsq_unit.hh:296
bool isInvalidate() const
Definition: packet.hh:517
Class that implements the actual LQ and SQ for each specific thread.
Definition: lsq_unit.hh:79
static PacketPtr createWrite(const RequestPtr req)
Definition: packet.hh:815
unsigned getSize() const
Definition: request.hh:552
The request is a Load locked/store conditional.
Definition: request.hh:147
void writeback(DynInstPtr &inst, PacketPtr pkt)
Writes back the instruction, sending it to IEW.
Bitfield< 1 > x
Definition: types.hh:105
Impl::O3CPU O3CPU
Definition: lsq_unit.hh:81
DynInstPtr inst
Instruction who initiated the access to memory.
Definition: lsq_unit.hh:288
std::shared_ptr< FaultBase > Fault
Definition: types.hh:184
Impl::CPUPol::IEW IEW
Definition: lsq_unit.hh:83
void handleLockedSnoopHit(XC *xc)
Definition: locked_mem.hh:96
void cprintf(const char *format, const Args &...args)
Definition: cprintf.hh:155
Addr getAddr() const
Definition: packet.hh:639
Addr cacheBlockMask
Address Mask for a cache block (e.g.
Definition: lsq_unit.hh:441

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