gem5  v20.1.0.0
lsq_impl.hh
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2012, 2014, 2017-2019 ARM Limited
3  * Copyright (c) 2013 Advanced Micro Devices, Inc.
4  * All rights reserved
5  *
6  * The license below extends only to copyright in the software and shall
7  * not be construed as granting a license to any other intellectual
8  * property including but not limited to intellectual property relating
9  * to a hardware implementation of the functionality of the software
10  * licensed hereunder. You may use the software subject to the license
11  * terms below provided that you ensure that this notice is replicated
12  * unmodified and in its entirety in all distributions of the software,
13  * modified or unmodified, in source code or in binary form.
14  *
15  * Copyright (c) 2005-2006 The Regents of The University of Michigan
16  * All rights reserved.
17  *
18  * Redistribution and use in source and binary forms, with or without
19  * modification, are permitted provided that the following conditions are
20  * met: redistributions of source code must retain the above copyright
21  * notice, this list of conditions and the following disclaimer;
22  * redistributions in binary form must reproduce the above copyright
23  * notice, this list of conditions and the following disclaimer in the
24  * documentation and/or other materials provided with the distribution;
25  * neither the name of the copyright holders nor the names of its
26  * contributors may be used to endorse or promote products derived from
27  * this software without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40  */
41 
42 #ifndef __CPU_O3_LSQ_IMPL_HH__
43 #define __CPU_O3_LSQ_IMPL_HH__
44 
45 #include <algorithm>
46 #include <list>
47 #include <string>
48 
49 #include "base/logging.hh"
50 #include "cpu/o3/cpu.hh"
51 #include "cpu/o3/lsq.hh"
52 #include "debug/Drain.hh"
53 #include "debug/Fetch.hh"
54 #include "debug/HtmCpu.hh"
55 #include "debug/LSQ.hh"
56 #include "debug/Writeback.hh"
57 #include "params/DerivO3CPU.hh"
58 
59 using namespace std;
60 
61 template <class Impl>
62 LSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params)
63  : cpu(cpu_ptr), iewStage(iew_ptr),
64  _cacheBlocked(false),
65  cacheStorePorts(params->cacheStorePorts), usedStorePorts(0),
66  cacheLoadPorts(params->cacheLoadPorts), usedLoadPorts(0),
67  lsqPolicy(params->smtLSQPolicy),
68  LQEntries(params->LQEntries),
69  SQEntries(params->SQEntries),
70  maxLQEntries(maxLSQAllocation(lsqPolicy, LQEntries, params->numThreads,
71  params->smtLSQThreshold)),
72  maxSQEntries(maxLSQAllocation(lsqPolicy, SQEntries, params->numThreads,
73  params->smtLSQThreshold)),
74  dcachePort(this, cpu_ptr),
75  numThreads(params->numThreads)
76 {
77  assert(numThreads > 0 && numThreads <= Impl::MaxThreads);
78 
79  //**********************************************/
80  //************ Handle SMT Parameters ***********/
81  //**********************************************/
82 
83  /* Run SMT olicy checks. */
84  if (lsqPolicy == SMTQueuePolicy::Dynamic) {
85  DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n");
86  } else if (lsqPolicy == SMTQueuePolicy::Partitioned) {
87  DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: "
88  "%i entries per LQ | %i entries per SQ\n",
90  } else if (lsqPolicy == SMTQueuePolicy::Threshold) {
91 
92  assert(params->smtLSQThreshold > params->LQEntries);
93  assert(params->smtLSQThreshold > params->SQEntries);
94 
95  DPRINTF(LSQ, "LSQ sharing policy set to Threshold: "
96  "%i entries per LQ | %i entries per SQ\n",
98  } else {
99  panic("Invalid LSQ sharing policy. Options are: Dynamic, "
100  "Partitioned, Threshold");
101  }
102 
103  thread.reserve(numThreads);
104  for (ThreadID tid = 0; tid < numThreads; tid++) {
105  thread.emplace_back(maxLQEntries, maxSQEntries);
106  thread[tid].init(cpu, iew_ptr, params, this, tid);
107  thread[tid].setDcachePort(&dcachePort);
108  }
109 }
110 
111 
112 template<class Impl>
113 std::string
115 {
116  return iewStage->name() + ".lsq";
117 }
118 
119 template<class Impl>
120 void
122 {
123  activeThreads = at_ptr;
124  assert(activeThreads != 0);
125 }
126 
127 template <class Impl>
128 void
130 {
131  assert(isDrained());
132 
133  for (ThreadID tid = 0; tid < numThreads; tid++)
134  thread[tid].drainSanityCheck();
135 }
136 
137 template <class Impl>
138 bool
140 {
141  bool drained(true);
142 
143  if (!lqEmpty()) {
144  DPRINTF(Drain, "Not drained, LQ not empty.\n");
145  drained = false;
146  }
147 
148  if (!sqEmpty()) {
149  DPRINTF(Drain, "Not drained, SQ not empty.\n");
150  drained = false;
151  }
152 
153  return drained;
154 }
155 
156 template <class Impl>
157 void
159 {
160  usedStorePorts = 0;
161  _cacheBlocked = false;
162 
163  for (ThreadID tid = 0; tid < numThreads; tid++) {
164  thread[tid].takeOverFrom();
165  }
166 }
167 
168 template <class Impl>
169 void
171 {
172  // Re-issue loads which got blocked on the per-cycle load ports limit.
173  if (usedLoadPorts == cacheLoadPorts && !_cacheBlocked)
174  iewStage->cacheUnblocked();
175 
176  usedLoadPorts = 0;
177  usedStorePorts = 0;
178 }
179 
180 template<class Impl>
181 bool
183 {
184  return _cacheBlocked;
185 }
186 
187 template<class Impl>
188 void
190 {
191  _cacheBlocked = v;
192 }
193 
194 template<class Impl>
195 bool
196 LSQ<Impl>::cachePortAvailable(bool is_load) const
197 {
198  bool ret;
199  if (is_load) {
200  ret = usedLoadPorts < cacheLoadPorts;
201  } else {
202  ret = usedStorePorts < cacheStorePorts;
203  }
204  return ret;
205 }
206 
207 template<class Impl>
208 void
210 {
211  assert(cachePortAvailable(is_load));
212  if (is_load) {
213  usedLoadPorts++;
214  } else {
215  usedStorePorts++;
216  }
217 }
218 
219 template<class Impl>
220 void
222 {
223  ThreadID tid = load_inst->threadNumber;
224 
225  thread[tid].insertLoad(load_inst);
226 }
227 
228 template<class Impl>
229 void
231 {
232  ThreadID tid = store_inst->threadNumber;
233 
234  thread[tid].insertStore(store_inst);
235 }
236 
237 template<class Impl>
238 Fault
240 {
241  ThreadID tid = inst->threadNumber;
242 
243  return thread[tid].executeLoad(inst);
244 }
245 
246 template<class Impl>
247 Fault
249 {
250  ThreadID tid = inst->threadNumber;
251 
252  return thread[tid].executeStore(inst);
253 }
254 
255 template<class Impl>
256 void
258 {
259  list<ThreadID>::iterator threads = activeThreads->begin();
260  list<ThreadID>::iterator end = activeThreads->end();
261 
262  while (threads != end) {
263  ThreadID tid = *threads++;
264 
265  if (numStoresToWB(tid) > 0) {
266  DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores "
267  "available for Writeback.\n", tid, numStoresToWB(tid));
268  }
269 
270  thread[tid].writebackStores();
271  }
272 }
273 
274 template<class Impl>
275 bool
277 {
278  /* Answers: Does Anybody Have a Violation?*/
279  list<ThreadID>::iterator threads = activeThreads->begin();
280  list<ThreadID>::iterator end = activeThreads->end();
281 
282  while (threads != end) {
283  ThreadID tid = *threads++;
284 
285  if (thread[tid].violation())
286  return true;
287  }
288 
289  return false;
290 }
291 
292 template <class Impl>
293 void
295 {
296  iewStage->cacheUnblocked();
297  cacheBlocked(false);
298 
299  for (ThreadID tid : *activeThreads) {
300  thread[tid].recvRetry();
301  }
302 }
303 
304 template <class Impl>
305 void
307 {
308  auto senderState = dynamic_cast<LSQSenderState*>(pkt->senderState);
309  thread[cpu->contextToThread(senderState->contextId())]
310  .completeDataAccess(pkt);
311 }
312 
313 template <class Impl>
314 bool
316 {
317  if (pkt->isError())
318  DPRINTF(LSQ, "Got error packet back for address: %#X\n",
319  pkt->getAddr());
320 
321  auto senderState = dynamic_cast<LSQSenderState*>(pkt->senderState);
322  panic_if(!senderState, "Got packet back with unknown sender state\n");
323 
324  thread[cpu->contextToThread(senderState->contextId())].recvTimingResp(pkt);
325 
326  if (pkt->isInvalidate()) {
327  // This response also contains an invalidate; e.g. this can be the case
328  // if cmd is ReadRespWithInvalidate.
329  //
330  // The calling order between completeDataAccess and checkSnoop matters.
331  // By calling checkSnoop after completeDataAccess, we ensure that the
332  // fault set by checkSnoop is not lost. Calling writeback (more
333  // specifically inst->completeAcc) in completeDataAccess overwrites
334  // fault, and in case this instruction requires squashing (as
335  // determined by checkSnoop), the ReExec fault set by checkSnoop would
336  // be lost otherwise.
337 
338  DPRINTF(LSQ, "received invalidation with response for addr:%#x\n",
339  pkt->getAddr());
340 
341  for (ThreadID tid = 0; tid < numThreads; tid++) {
342  thread[tid].checkSnoop(pkt);
343  }
344  }
345  // Update the LSQRequest state (this may delete the request)
346  senderState->request()->packetReplied();
347 
348  return true;
349 }
350 
351 template <class Impl>
352 void
354 {
355  DPRINTF(LSQ, "received pkt for addr:%#x %s\n", pkt->getAddr(),
356  pkt->cmdString());
357 
358  // must be a snoop
359  if (pkt->isInvalidate()) {
360  DPRINTF(LSQ, "received invalidation for addr:%#x\n",
361  pkt->getAddr());
362  for (ThreadID tid = 0; tid < numThreads; tid++) {
363  thread[tid].checkSnoop(pkt);
364  }
365  }
366 }
367 
368 template<class Impl>
369 int
371 {
372  unsigned total = 0;
373 
374  list<ThreadID>::iterator threads = activeThreads->begin();
375  list<ThreadID>::iterator end = activeThreads->end();
376 
377  while (threads != end) {
378  ThreadID tid = *threads++;
379 
380  total += getCount(tid);
381  }
382 
383  return total;
384 }
385 
386 template<class Impl>
387 int
389 {
390  unsigned total = 0;
391 
392  list<ThreadID>::iterator threads = activeThreads->begin();
393  list<ThreadID>::iterator end = activeThreads->end();
394 
395  while (threads != end) {
396  ThreadID tid = *threads++;
397 
398  total += numLoads(tid);
399  }
400 
401  return total;
402 }
403 
404 template<class Impl>
405 int
407 {
408  unsigned total = 0;
409 
410  list<ThreadID>::iterator threads = activeThreads->begin();
411  list<ThreadID>::iterator end = activeThreads->end();
412 
413  while (threads != end) {
414  ThreadID tid = *threads++;
415 
416  total += thread[tid].numStores();
417  }
418 
419  return total;
420 }
421 
422 template<class Impl>
423 unsigned
425 {
426  unsigned total = 0;
427 
428  list<ThreadID>::iterator threads = activeThreads->begin();
429  list<ThreadID>::iterator end = activeThreads->end();
430 
431  while (threads != end) {
432  ThreadID tid = *threads++;
433 
434  total += thread[tid].numFreeLoadEntries();
435  }
436 
437  return total;
438 }
439 
440 template<class Impl>
441 unsigned
443 {
444  unsigned total = 0;
445 
446  list<ThreadID>::iterator threads = activeThreads->begin();
447  list<ThreadID>::iterator end = activeThreads->end();
448 
449  while (threads != end) {
450  ThreadID tid = *threads++;
451 
452  total += thread[tid].numFreeStoreEntries();
453  }
454 
455  return total;
456 }
457 
458 template<class Impl>
459 unsigned
461 {
462  return thread[tid].numFreeLoadEntries();
463 }
464 
465 template<class Impl>
466 unsigned
468 {
469  return thread[tid].numFreeStoreEntries();
470 }
471 
472 template<class Impl>
473 bool
475 {
476  list<ThreadID>::iterator threads = activeThreads->begin();
477  list<ThreadID>::iterator end = activeThreads->end();
478 
479  while (threads != end) {
480  ThreadID tid = *threads++;
481 
482  if (!(thread[tid].lqFull() || thread[tid].sqFull()))
483  return false;
484  }
485 
486  return true;
487 }
488 
489 template<class Impl>
490 bool
492 {
493  //@todo: Change to Calculate All Entries for
494  //Dynamic Policy
495  if (lsqPolicy == SMTQueuePolicy::Dynamic)
496  return isFull();
497  else
498  return thread[tid].lqFull() || thread[tid].sqFull();
499 }
500 
501 template<class Impl>
502 bool
504 {
505  return lqEmpty() && sqEmpty();
506 }
507 
508 template<class Impl>
509 bool
511 {
512  list<ThreadID>::const_iterator threads = activeThreads->begin();
513  list<ThreadID>::const_iterator end = activeThreads->end();
514 
515  while (threads != end) {
516  ThreadID tid = *threads++;
517 
518  if (!thread[tid].lqEmpty())
519  return false;
520  }
521 
522  return true;
523 }
524 
525 template<class Impl>
526 bool
528 {
529  list<ThreadID>::const_iterator threads = activeThreads->begin();
530  list<ThreadID>::const_iterator end = activeThreads->end();
531 
532  while (threads != end) {
533  ThreadID tid = *threads++;
534 
535  if (!thread[tid].sqEmpty())
536  return false;
537  }
538 
539  return true;
540 }
541 
542 template<class Impl>
543 bool
545 {
546  list<ThreadID>::iterator threads = activeThreads->begin();
547  list<ThreadID>::iterator end = activeThreads->end();
548 
549  while (threads != end) {
550  ThreadID tid = *threads++;
551 
552  if (!thread[tid].lqFull())
553  return false;
554  }
555 
556  return true;
557 }
558 
559 template<class Impl>
560 bool
562 {
563  //@todo: Change to Calculate All Entries for
564  //Dynamic Policy
565  if (lsqPolicy == SMTQueuePolicy::Dynamic)
566  return lqFull();
567  else
568  return thread[tid].lqFull();
569 }
570 
571 template<class Impl>
572 bool
574 {
575  list<ThreadID>::iterator threads = activeThreads->begin();
576  list<ThreadID>::iterator end = activeThreads->end();
577 
578  while (threads != end) {
579  ThreadID tid = *threads++;
580 
581  if (!sqFull(tid))
582  return false;
583  }
584 
585  return true;
586 }
587 
588 template<class Impl>
589 bool
591 {
592  //@todo: Change to Calculate All Entries for
593  //Dynamic Policy
594  if (lsqPolicy == SMTQueuePolicy::Dynamic)
595  return sqFull();
596  else
597  return thread[tid].sqFull();
598 }
599 
600 template<class Impl>
601 bool
603 {
604  list<ThreadID>::iterator threads = activeThreads->begin();
605  list<ThreadID>::iterator end = activeThreads->end();
606 
607  while (threads != end) {
608  ThreadID tid = *threads++;
609 
610  if (!thread[tid].isStalled())
611  return false;
612  }
613 
614  return true;
615 }
616 
617 template<class Impl>
618 bool
620 {
621  if (lsqPolicy == SMTQueuePolicy::Dynamic)
622  return isStalled();
623  else
624  return thread[tid].isStalled();
625 }
626 
627 template<class Impl>
628 bool
630 {
631  list<ThreadID>::iterator threads = activeThreads->begin();
632  list<ThreadID>::iterator end = activeThreads->end();
633 
634  while (threads != end) {
635  ThreadID tid = *threads++;
636 
637  if (hasStoresToWB(tid))
638  return true;
639  }
640 
641  return false;
642 }
643 
644 template<class Impl>
645 bool
647 {
648  list<ThreadID>::iterator threads = activeThreads->begin();
649  list<ThreadID>::iterator end = activeThreads->end();
650 
651  while (threads != end) {
652  ThreadID tid = *threads++;
653 
654  if (willWB(tid))
655  return true;
656  }
657 
658  return false;
659 }
660 
661 template<class Impl>
662 void
664 {
665  list<ThreadID>::const_iterator threads = activeThreads->begin();
666  list<ThreadID>::const_iterator end = activeThreads->end();
667 
668  while (threads != end) {
669  ThreadID tid = *threads++;
670 
671  thread[tid].dumpInsts();
672  }
673 }
674 
675 template<class Impl>
676 Fault
677 LSQ<Impl>::pushRequest(const DynInstPtr& inst, bool isLoad, uint8_t *data,
678  unsigned int size, Addr addr, Request::Flags flags,
679  uint64_t *res, AtomicOpFunctorPtr amo_op,
680  const std::vector<bool>& byte_enable)
681 {
682  // This comming request can be either load, store or atomic.
683  // Atomic request has a corresponding pointer to its atomic memory
684  // operation
685  bool isAtomic M5_VAR_USED = !isLoad && amo_op;
686 
687  ThreadID tid = cpu->contextToThread(inst->contextId());
688  auto cacheLineSize = cpu->cacheLineSize();
689  bool needs_burst = transferNeedsBurst(addr, size, cacheLineSize);
690  LSQRequest* req = nullptr;
691 
692  // Atomic requests that access data across cache line boundary are
693  // currently not allowed since the cache does not guarantee corresponding
694  // atomic memory operations to be executed atomically across a cache line.
695  // For ISAs such as x86 that supports cross-cache-line atomic instructions,
696  // the cache needs to be modified to perform atomic update to both cache
697  // lines. For now, such cross-line update is not supported.
698  assert(!isAtomic || (isAtomic && !needs_burst));
699 
700  const bool htm_cmd = isLoad && (flags & Request::HTM_CMD);
701 
702  if (inst->translationStarted()) {
703  req = inst->savedReq;
704  assert(req);
705  } else {
706  if (htm_cmd) {
707  assert(addr == 0x0lu);
708  assert(size == 8);
709  req = new HtmCmdRequest(&thread[tid], inst, flags);
710  } else if (needs_burst) {
711  req = new SplitDataRequest(&thread[tid], inst, isLoad, addr,
712  size, flags, data, res);
713  } else {
714  req = new SingleDataRequest(&thread[tid], inst, isLoad, addr,
715  size, flags, data, res, std::move(amo_op));
716  }
717  assert(req);
718  if (!byte_enable.empty()) {
719  req->_byteEnable = byte_enable;
720  }
721  inst->setRequest();
722  req->taskId(cpu->taskId());
723 
724  // There might be fault from a previous execution attempt if this is
725  // a strictly ordered load
726  inst->getFault() = NoFault;
727 
728  req->initiateTranslation();
729  }
730 
731  /* This is the place were instructions get the effAddr. */
732  if (req->isTranslationComplete()) {
733  if (req->isMemAccessRequired()) {
734  inst->effAddr = req->getVaddr();
735  inst->effSize = size;
736  inst->effAddrValid(true);
737 
738  if (cpu->checker) {
739  inst->reqToVerify = std::make_shared<Request>(*req->request());
740  }
741  Fault fault;
742  if (isLoad)
743  fault = cpu->read(req, inst->lqIdx);
744  else
745  fault = cpu->write(req, data, inst->sqIdx);
746  // inst->getFault() may have the first-fault of a
747  // multi-access split request at this point.
748  // Overwrite that only if we got another type of fault
749  // (e.g. re-exec).
750  if (fault != NoFault)
751  inst->getFault() = fault;
752  } else if (isLoad) {
753  inst->setMemAccPredicate(false);
754  // Commit will have to clean up whatever happened. Set this
755  // instruction as executed.
756  inst->setExecuted();
757  }
758  }
759 
760  if (inst->traceData)
761  inst->traceData->setMem(addr, size, flags);
762 
763  return inst->getFault();
764 }
765 
766 template<class Impl>
767 void
770 {
771  _fault.push_back(fault);
774  /* If the instruction has been squahsed, let the request know
775  * as it may have to self-destruct. */
776  if (_inst->isSquashed()) {
777  this->squashTranslation();
778  } else {
779  _inst->strictlyOrdered(req->isStrictlyOrdered());
780 
781  flags.set(Flag::TranslationFinished);
782  if (fault == NoFault) {
783  _inst->physEffAddr = req->getPaddr();
784  _inst->memReqFlags = req->getFlags();
785  if (req->isCondSwap()) {
786  assert(_res);
787  req->setExtraData(*_res);
788  }
789  setState(State::Request);
790  } else {
792  }
793 
794  LSQRequest::_inst->fault = fault;
795  LSQRequest::_inst->translationCompleted(true);
796  }
797 }
798 
799 template<class Impl>
800 void
803 {
804  int i;
805  for (i = 0; i < _requests.size() && _requests[i] != req; i++);
806  assert(i < _requests.size());
807  _fault[i] = fault;
808 
809  numInTranslationFragments--;
810  numTranslatedFragments++;
811 
812  if (fault == NoFault)
813  mainReq->setFlags(req->getFlags());
814 
815  if (numTranslatedFragments == _requests.size()) {
816  if (_inst->isSquashed()) {
817  this->squashTranslation();
818  } else {
819  _inst->strictlyOrdered(mainReq->isStrictlyOrdered());
820  flags.set(Flag::TranslationFinished);
821  _inst->translationCompleted(true);
822 
823  for (i = 0; i < _fault.size() && _fault[i] == NoFault; i++);
824  if (i > 0) {
825  _inst->physEffAddr = request(0)->getPaddr();
826  _inst->memReqFlags = mainReq->getFlags();
827  if (mainReq->isCondSwap()) {
828  assert (i == _fault.size());
829  assert(_res);
830  mainReq->setExtraData(*_res);
831  }
832  if (i == _fault.size()) {
833  _inst->fault = NoFault;
834  setState(State::Request);
835  } else {
836  _inst->fault = _fault[i];
837  setState(State::PartialFault);
838  }
839  } else {
840  _inst->fault = _fault[0];
841  setState(State::Fault);
842  }
843  }
844 
845  }
846 }
847 
848 template<class Impl>
849 void
851 {
852  assert(_requests.size() == 0);
853 
854  this->addRequest(_addr, _size, _byteEnable);
855 
856  if (_requests.size() > 0) {
857  _requests.back()->setReqInstSeqNum(_inst->seqNum);
858  _requests.back()->taskId(_taskId);
859  _inst->translationStarted(true);
860  setState(State::Translation);
861  flags.set(Flag::TranslationStarted);
862 
863  _inst->savedReq = this;
864  sendFragmentToTranslation(0);
865  } else {
866  _inst->setMemAccPredicate(false);
867  }
868 }
869 
870 template<class Impl>
871 PacketPtr
873 {
874  return _mainPacket;
875 }
876 
877 template<class Impl>
880 {
881  return mainReq;
882 }
883 
884 template<class Impl>
885 void
887 {
888  auto cacheLineSize = _port.cacheLineSize();
889  Addr base_addr = _addr;
890  Addr next_addr = addrBlockAlign(_addr + cacheLineSize, cacheLineSize);
891  Addr final_addr = addrBlockAlign(_addr + _size, cacheLineSize);
892  uint32_t size_so_far = 0;
893 
894  mainReq = std::make_shared<Request>(base_addr,
895  _size, _flags, _inst->requestorId(),
896  _inst->instAddr(), _inst->contextId());
897  if (!_byteEnable.empty()) {
898  mainReq->setByteEnable(_byteEnable);
899  }
900 
901  // Paddr is not used in mainReq. However, we will accumulate the flags
902  // from the sub requests into mainReq by calling setFlags() in finish().
903  // setFlags() assumes that paddr is set so flip the paddr valid bit here to
904  // avoid a potential assert in setFlags() when we call it from finish().
905  mainReq->setPaddr(0);
906 
907  /* Get the pre-fix, possibly unaligned. */
908  if (_byteEnable.empty()) {
909  this->addRequest(base_addr, next_addr - base_addr, _byteEnable);
910  } else {
911  auto it_start = _byteEnable.begin();
912  auto it_end = _byteEnable.begin() + (next_addr - base_addr);
913  this->addRequest(base_addr, next_addr - base_addr,
914  std::vector<bool>(it_start, it_end));
915  }
916  size_so_far = next_addr - base_addr;
917 
918  /* We are block aligned now, reading whole blocks. */
919  base_addr = next_addr;
920  while (base_addr != final_addr) {
921  if (_byteEnable.empty()) {
922  this->addRequest(base_addr, cacheLineSize, _byteEnable);
923  } else {
924  auto it_start = _byteEnable.begin() + size_so_far;
925  auto it_end = _byteEnable.begin() + size_so_far + cacheLineSize;
926  this->addRequest(base_addr, cacheLineSize,
927  std::vector<bool>(it_start, it_end));
928  }
929  size_so_far += cacheLineSize;
930  base_addr += cacheLineSize;
931  }
932 
933  /* Deal with the tail. */
934  if (size_so_far < _size) {
935  if (_byteEnable.empty()) {
936  this->addRequest(base_addr, _size - size_so_far, _byteEnable);
937  } else {
938  auto it_start = _byteEnable.begin() + size_so_far;
939  auto it_end = _byteEnable.end();
940  this->addRequest(base_addr, _size - size_so_far,
941  std::vector<bool>(it_start, it_end));
942  }
943  }
944 
945  if (_requests.size() > 0) {
946  /* Setup the requests and send them to translation. */
947  for (auto& r: _requests) {
948  r->setReqInstSeqNum(_inst->seqNum);
949  r->taskId(_taskId);
950  }
951 
952  _inst->translationStarted(true);
953  setState(State::Translation);
954  flags.set(Flag::TranslationStarted);
955  this->_inst->savedReq = this;
956  numInTranslationFragments = 0;
957  numTranslatedFragments = 0;
958  _fault.resize(_requests.size());
959 
960  for (uint32_t i = 0; i < _requests.size(); i++) {
961  sendFragmentToTranslation(i);
962  }
963  } else {
964  _inst->setMemAccPredicate(false);
965  }
966 }
967 
968 template<class Impl>
969 void
971 {
972  numInTranslationFragments++;
973  _port.dTLB()->translateTiming(
974  this->request(i),
975  this->_inst->thread->getTC(), this,
976  this->isLoad() ? BaseTLB::Read : BaseTLB::Write);
977 }
978 
979 template<class Impl>
980 bool
982 {
983  assert(_numOutstandingPackets == 1);
984  auto state = dynamic_cast<LSQSenderState*>(pkt->senderState);
985  flags.set(Flag::Complete);
986  state->outstanding--;
987  assert(pkt == _packets.front());
988  _port.completeDataAccess(pkt);
989  return true;
990 }
991 
992 template<class Impl>
993 bool
995 {
996  auto state = dynamic_cast<LSQSenderState*>(pkt->senderState);
997  uint32_t pktIdx = 0;
998  while (pktIdx < _packets.size() && pkt != _packets[pktIdx])
999  pktIdx++;
1000  assert(pktIdx < _packets.size());
1001  numReceivedPackets++;
1002  state->outstanding--;
1003  if (numReceivedPackets == _packets.size()) {
1004  flags.set(Flag::Complete);
1005  /* Assemble packets. */
1006  PacketPtr resp = isLoad()
1007  ? Packet::createRead(mainReq)
1008  : Packet::createWrite(mainReq);
1009  if (isLoad())
1010  resp->dataStatic(_inst->memData);
1011  else
1012  resp->dataStatic(_data);
1013  resp->senderState = _senderState;
1014  _port.completeDataAccess(resp);
1015  delete resp;
1016  }
1017  return true;
1018 }
1019 
1020 template<class Impl>
1021 void
1023 {
1024  assert(_senderState);
1025  /* Retries do not create new packets. */
1026  if (_packets.size() == 0) {
1027  _packets.push_back(
1028  isLoad()
1029  ? Packet::createRead(request())
1030  : Packet::createWrite(request()));
1031  _packets.back()->dataStatic(_inst->memData);
1032  _packets.back()->senderState = _senderState;
1033 
1034  // hardware transactional memory
1035  // If request originates in a transaction (not necessarily a HtmCmd),
1036  // then the packet should be marked as such.
1037  if (_inst->inHtmTransactionalState()) {
1038  _packets.back()->setHtmTransactional(
1039  _inst->getHtmTransactionUid());
1040 
1041  DPRINTF(HtmCpu,
1042  "HTM %s pc=0x%lx - vaddr=0x%lx - paddr=0x%lx - htmUid=%u\n",
1043  isLoad() ? "LD" : "ST",
1044  _inst->instAddr(),
1045  _packets.back()->req->hasVaddr() ?
1046  _packets.back()->req->getVaddr() : 0lu,
1047  _packets.back()->getAddr(),
1048  _inst->getHtmTransactionUid());
1049  }
1050  }
1051  assert(_packets.size() == 1);
1052 }
1053 
1054 template<class Impl>
1055 void
1057 {
1058  /* Extra data?? */
1059  Addr base_address = _addr;
1060 
1061  if (_packets.size() == 0) {
1062  /* New stuff */
1063  if (isLoad()) {
1064  _mainPacket = Packet::createRead(mainReq);
1065  _mainPacket->dataStatic(_inst->memData);
1066 
1067  // hardware transactional memory
1068  // If request originates in a transaction,
1069  // packet should be marked as such
1070  if (_inst->inHtmTransactionalState()) {
1071  _mainPacket->setHtmTransactional(
1072  _inst->getHtmTransactionUid());
1073  DPRINTF(HtmCpu,
1074  "HTM LD.0 pc=0x%lx-vaddr=0x%lx-paddr=0x%lx-htmUid=%u\n",
1075  _inst->instAddr(),
1076  _mainPacket->req->hasVaddr() ?
1077  _mainPacket->req->getVaddr() : 0lu,
1078  _mainPacket->getAddr(),
1079  _inst->getHtmTransactionUid());
1080  }
1081  }
1082  for (int i = 0; i < _requests.size() && _fault[i] == NoFault; i++) {
1083  RequestPtr r = _requests[i];
1084  PacketPtr pkt = isLoad() ? Packet::createRead(r)
1086  ptrdiff_t offset = r->getVaddr() - base_address;
1087  if (isLoad()) {
1088  pkt->dataStatic(_inst->memData + offset);
1089  } else {
1090  uint8_t* req_data = new uint8_t[r->getSize()];
1091  std::memcpy(req_data,
1092  _inst->memData + offset,
1093  r->getSize());
1094  pkt->dataDynamic(req_data);
1095  }
1096  pkt->senderState = _senderState;
1097  _packets.push_back(pkt);
1098 
1099  // hardware transactional memory
1100  // If request originates in a transaction,
1101  // packet should be marked as such
1102  if (_inst->inHtmTransactionalState()) {
1103  _packets.back()->setHtmTransactional(
1104  _inst->getHtmTransactionUid());
1105  DPRINTF(HtmCpu,
1106  "HTM %s.%d pc=0x%lx-vaddr=0x%lx-paddr=0x%lx-htmUid=%u\n",
1107  isLoad() ? "LD" : "ST",
1108  i+1,
1109  _inst->instAddr(),
1110  _packets.back()->req->hasVaddr() ?
1111  _packets.back()->req->getVaddr() : 0lu,
1112  _packets.back()->getAddr(),
1113  _inst->getHtmTransactionUid());
1114  }
1115  }
1116  }
1117  assert(_packets.size() > 0);
1118 }
1119 
1120 template<class Impl>
1121 void
1123 {
1124  assert(_numOutstandingPackets == 0);
1125  if (lsqUnit()->trySendPacket(isLoad(), _packets.at(0)))
1126  _numOutstandingPackets = 1;
1127 }
1128 
1129 template<class Impl>
1130 void
1132 {
1133  /* Try to send the packets. */
1134  while (numReceivedPackets + _numOutstandingPackets < _packets.size() &&
1135  lsqUnit()->trySendPacket(isLoad(),
1136  _packets.at(numReceivedPackets + _numOutstandingPackets))) {
1137  _numOutstandingPackets++;
1138  }
1139 }
1140 
1141 template<class Impl>
1142 Cycles
1145 {
1146  return pkt->req->localAccessor(thread, pkt);
1147 }
1148 
1149 template<class Impl>
1150 Cycles
1152  ThreadContext *thread, PacketPtr mainPkt)
1153 {
1154  Cycles delay(0);
1155  unsigned offset = 0;
1156 
1157  for (auto r: _requests) {
1158  PacketPtr pkt =
1159  new Packet(r, isLoad() ? MemCmd::ReadReq : MemCmd::WriteReq);
1160  pkt->dataStatic(mainPkt->getPtr<uint8_t>() + offset);
1161  Cycles d = r->localAccessor(thread, pkt);
1162  if (d > delay)
1163  delay = d;
1164  offset += r->getSize();
1165  delete pkt;
1166  }
1167  return delay;
1168 }
1169 
1170 template<class Impl>
1171 bool
1173 {
1174  return ( (LSQRequest::_requests[0]->getPaddr() & blockMask) == blockAddr);
1175 }
1176 
1192 template<class Impl>
1193 bool
1195 {
1196  bool is_hit = false;
1197  for (auto &r: _requests) {
1207  if (r->hasPaddr() && (r->getPaddr() & blockMask) == blockAddr) {
1208  is_hit = true;
1209  break;
1210  }
1211  }
1212  return is_hit;
1213 }
1214 
1215 template <class Impl>
1216 bool
1218 {
1219  return lsq->recvTimingResp(pkt);
1220 }
1221 
1222 template <class Impl>
1223 void
1225 {
1226  for (ThreadID tid = 0; tid < cpu->numThreads; tid++) {
1227  if (cpu->getCpuAddrMonitor(tid)->doMonitor(pkt)) {
1228  cpu->wakeup(tid);
1229  }
1230  }
1231  lsq->recvTimingSnoopReq(pkt);
1232 }
1233 
1234 template <class Impl>
1235 void
1237 {
1238  lsq->recvReqRetry();
1239 }
1240 
1241 template<class Impl>
1243  const DynInstPtr& inst,
1244  const Request::Flags& flags_) :
1245  SingleDataRequest(port, inst, true, 0x0lu, 8, flags_,
1246  nullptr, nullptr, nullptr)
1247 {
1248  assert(_requests.size() == 0);
1249 
1250  this->addRequest(_addr, _size, _byteEnable);
1251 
1252  if (_requests.size() > 0) {
1253  _requests.back()->setReqInstSeqNum(_inst->seqNum);
1254  _requests.back()->taskId(_taskId);
1255  _requests.back()->setPaddr(_addr);
1256  _requests.back()->setInstCount(_inst->getCpuPtr()->totalInsts());
1257 
1258  _inst->strictlyOrdered(_requests.back()->isStrictlyOrdered());
1259  _inst->fault = NoFault;
1260  _inst->physEffAddr = _requests.back()->getPaddr();
1261  _inst->memReqFlags = _requests.back()->getFlags();
1262  _inst->savedReq = this;
1263 
1264  setState(State::Translation);
1265  } else {
1266  panic("unexpected behaviour");
1267  }
1268 }
1269 
1270 template<class Impl>
1271 void
1273 {
1274  // Transaction commands are implemented as loads to avoid significant
1275  // changes to the cpu and memory interfaces
1276  // The virtual and physical address uses a dummy value of 0x00
1277  // Address translation does not really occur thus the code below
1278 
1279  flags.set(Flag::TranslationStarted);
1280  flags.set(Flag::TranslationFinished);
1281 
1282  _inst->translationStarted(true);
1283  _inst->translationCompleted(true);
1284 
1285  setState(State::Request);
1286 }
1287 
1288 template<class Impl>
1289 void
1292 {
1293  panic("unexpected behaviour");
1294 }
1295 
1296 #endif//__CPU_O3_LSQ_IMPL_HH__
LSQ::insertStore
void insertStore(const DynInstPtr &store_inst)
Inserts a store into the LSQ.
Definition: lsq_impl.hh:230
LSQ::thread
std::vector< LSQUnit > thread
The LSQ units for individual threads.
Definition: lsq.hh:1182
Packet::isError
bool isError() const
Definition: packet.hh:583
AtomicOpFunctorPtr
std::unique_ptr< AtomicOpFunctor > AtomicOpFunctorPtr
Definition: amo.hh:239
LSQ::SingleDataRequest::handleLocalAccess
virtual Cycles handleLocalAccess(ThreadContext *thread, PacketPtr pkt)
Memory mapped IPR accesses.
Definition: lsq_impl.hh:1143
LSQ::willWB
bool willWB()
Returns if the LSQ will write back to memory this cycle.
Definition: lsq_impl.hh:646
LSQ::executeStore
Fault executeStore(const DynInstPtr &inst)
Executes a store.
Definition: lsq_impl.hh:248
LSQ::maxSQEntries
unsigned maxSQEntries
Max SQ Size - Used to Enforce Sharing Policies.
Definition: lsq.hh:1176
BaseTLB::Read
@ Read
Definition: tlb.hh:57
data
const char data[]
Definition: circlebuf.test.cc:42
LSQ::HtmCmdRequest::finish
virtual void finish(const Fault &fault, const RequestPtr &req, ThreadContext *tc, BaseTLB::Mode mode)
Definition: lsq_impl.hh:1290
Packet::getAddr
Addr getAddr() const
Definition: packet.hh:754
LSQ::SplitDataRequest::mainPacket
virtual PacketPtr mainPacket()
Definition: lsq_impl.hh:872
LSQ::SplitDataRequest::mainRequest
virtual RequestPtr mainRequest()
Definition: lsq_impl.hh:879
LSQ::insertLoad
void insertLoad(const DynInstPtr &load_inst)
Inserts a load into the LSQ.
Definition: lsq_impl.hh:221
LSQ::sqEmpty
bool sqEmpty() const
Returns if all of the SQs are empty.
Definition: lsq_impl.hh:527
ArmISA::i
Bitfield< 7 > i
Definition: miscregs_types.hh:63
LSQ::LSQ
LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params)
Constructs an LSQ with the given parameters.
Definition: lsq_impl.hh:62
ThreadID
int16_t ThreadID
Thread index/ID type.
Definition: types.hh:227
LSQ::LSQRequest::numInTranslationFragments
uint32_t numInTranslationFragments
Definition: lsq.hh:278
LSQ::LSQRequest::isMemAccessRequired
bool isMemAccessRequired()
Definition: lsq.hh:618
Flags< FlagsType >
LSQ::LSQSenderState::outstanding
uint8_t outstanding
Number of outstanding packets to complete.
Definition: lsq.hh:94
LSQ::SplitDataRequest::initiateTranslation
virtual void initiateTranslation()
Definition: lsq_impl.hh:886
LSQ::LSQRequest::flags
FlagsType flags
Definition: lsq.hh:263
BaseTLB::Mode
Mode
Definition: tlb.hh:57
MemCmd::ReadReq
@ ReadReq
Definition: packet.hh:82
LSQ::DcachePort::recvTimingResp
virtual bool recvTimingResp(PacketPtr pkt)
Timing version of receive.
Definition: lsq_impl.hh:1217
LSQ::recvTimingResp
bool recvTimingResp(PacketPtr pkt)
Handles writing back and completing the load or store that has returned from memory.
Definition: lsq_impl.hh:315
Packet::isInvalidate
bool isInvalidate() const
Definition: packet.hh:571
RequestPtr
std::shared_ptr< Request > RequestPtr
Definition: request.hh:82
Packet::req
RequestPtr req
A pointer to the original request.
Definition: packet.hh:340
LSQ::SingleDataRequest::buildPackets
virtual void buildPackets()
Definition: lsq_impl.hh:1022
LSQ::recvReqRetry
void recvReqRetry()
Retry the previous send that failed.
Definition: lsq_impl.hh:294
Packet::dataDynamic
void dataDynamic(T *p)
Set the data pointer to a value that should have delete [] called on it.
Definition: packet.hh:1145
std::vector< bool >
LSQ::SingleDataRequest::recvTimingResp
virtual bool recvTimingResp(PacketPtr pkt)
Definition: lsq_impl.hh:981
Request::HTM_CMD
static const FlagsType HTM_CMD
Definition: request.hh:236
LSQ::LSQRequest::sendFragmentToTranslation
void sendFragmentToTranslation(int i)
Definition: lsq_impl.hh:970
LSQ::numStores
int numStores()
Returns the total number of stores in the store queue.
Definition: lsq_impl.hh:406
LSQ::violation
bool violation()
Returns whether or not there was a memory ordering violation.
Definition: lsq_impl.hh:276
LSQ::SplitDataRequest::finish
virtual void finish(const Fault &fault, const RequestPtr &req, ThreadContext *tc, BaseTLB::Mode mode)
Definition: lsq_impl.hh:801
LSQ::isEmpty
bool isEmpty() const
Returns if the LSQ is empty (both LQ and SQ are empty).
Definition: lsq_impl.hh:503
LSQ::numLoads
int numLoads()
Returns the total number of loads in the load queue.
Definition: lsq_impl.hh:388
LSQ::tick
void tick()
Ticks the LSQ.
Definition: lsq_impl.hh:170
LSQ::lqFull
bool lqFull()
Returns if any of the LQs are full.
Definition: lsq_impl.hh:544
LSQ::isFull
bool isFull()
Returns if the LSQ is full (either LQ or SQ is full).
Definition: lsq_impl.hh:474
LSQ::completeDataAccess
void completeDataAccess(PacketPtr pkt)
Definition: lsq_impl.hh:306
LSQ::isDrained
bool isDrained() const
Has the LSQ drained?
Definition: lsq_impl.hh:139
LSQ::LSQRequest::_requests
std::vector< RequestPtr > _requests
Definition: lsq.hh:292
MemCmd::WriteReq
@ WriteReq
Definition: packet.hh:85
LSQ::SplitDataRequest::sendPacketToCache
virtual void sendPacketToCache()
Definition: lsq_impl.hh:1131
LSQ::takeOverFrom
void takeOverFrom()
Takes over execution from another CPU's thread.
Definition: lsq_impl.hh:158
LSQ::dcachePort
DcachePort dcachePort
Data port.
Definition: lsq.hh:1179
LSQ::O3CPU
Impl::O3CPU O3CPU
Definition: lsq.hh:66
LSQUnit
Class that implements the actual LQ and SQ for each specific thread.
Definition: lsq_unit.hh:78
LSQ::LSQRequest::_byteEnable
std::vector< bool > _byteEnable
Definition: lsq.hh:298
LSQ::LSQRequest::_taskId
uint32_t _taskId
Definition: lsq.hh:289
LSQ::drainSanityCheck
void drainSanityCheck() const
Perform sanity checks after a drain.
Definition: lsq_impl.hh:129
LSQ::LSQRequest::addRequest
void addRequest(Addr addr, unsigned size, const std::vector< bool > &byte_enable)
Helper function used to add a (sub)request, given its address addr, size size and byte-enable mask by...
Definition: lsq.hh:406
addrBlockAlign
Addr addrBlockAlign(Addr addr, Addr block_size)
Returns the address of the closest aligned fixed-size block to the given address.
Definition: utils.hh:63
LSQ::isStalled
bool isStalled()
Returns if the LSQ is stalled due to a memory operation that must be replayed.
Definition: lsq_impl.hh:602
ThreadContext
ThreadContext is the external interface to all thread state for anything outside of the CPU.
Definition: thread_context.hh:88
LSQ
Definition: lsq.hh:62
LSQ::cachePortAvailable
bool cachePortAvailable(bool is_load) const
Is any store port available to use?
Definition: lsq_impl.hh:196
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:234
LSQ::SingleDataRequest::sendPacketToCache
virtual void sendPacketToCache()
Definition: lsq_impl.hh:1122
Packet::cmdString
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
Definition: packet.hh:551
ArmISA::d
Bitfield< 9 > d
Definition: miscregs_types.hh:60
Fault
std::shared_ptr< FaultBase > Fault
Definition: types.hh:240
LSQ::LSQRequest::_res
uint64_t * _res
Definition: lsq.hh:294
Packet::createRead
static PacketPtr createRead(const RequestPtr &req)
Constructor-like methods that return Packets based on Request objects.
Definition: packet.hh:980
MipsISA::r
r
Definition: pra_constants.hh:95
LSQ::LSQSenderState
Derived class to hold any sender state the LSQ needs.
Definition: lsq.hh:73
LSQ::cachePortBusy
void cachePortBusy(bool is_load)
Another store port is in use.
Definition: lsq_impl.hh:209
LSQ::numFreeStoreEntries
unsigned numFreeStoreEntries()
Returns the number of free store entries.
Definition: lsq_impl.hh:442
LSQ::SplitDataRequest::buildPackets
virtual void buildPackets()
Definition: lsq_impl.hh:1056
LSQ::executeLoad
Fault executeLoad(const DynInstPtr &inst)
Executes a load.
Definition: lsq_impl.hh:239
ArmISA::mode
Bitfield< 4, 0 > mode
Definition: miscregs_types.hh:70
LSQ::LSQRequest::isTranslationComplete
bool isTranslationComplete()
Definition: lsq.hh:591
LSQ::IEW
Impl::CPUPol::IEW IEW
Definition: lsq.hh:68
LSQ::HtmCmdRequest
Definition: lsq.hh:750
LSQ::lqEmpty
bool lqEmpty() const
Returns if all of the LQs are empty.
Definition: lsq_impl.hh:510
Flags::set
void set(Type flags)
Definition: flags.hh:87
LSQ::DynInstPtr
Impl::DynInstPtr DynInstPtr
Definition: lsq.hh:67
LSQ::pushRequest
Fault pushRequest(const DynInstPtr &inst, bool isLoad, uint8_t *data, unsigned int size, Addr addr, Request::Flags flags, uint64_t *res, AtomicOpFunctorPtr amo_op, const std::vector< bool > &byte_enable)
Definition: lsq_impl.hh:677
LSQ::getCount
int getCount()
Returns the number of instructions in all of the queues.
Definition: lsq_impl.hh:370
LSQ::LSQRequest::initiateTranslation
virtual void initiateTranslation()=0
NoFault
constexpr decltype(nullptr) NoFault
Definition: types.hh:245
LSQ::writebackStores
void writebackStores()
Attempts to write back stores until all cache ports are used or the interface becomes blocked.
Definition: lsq_impl.hh:257
LSQ::SingleDataRequest::finish
virtual void finish(const Fault &fault, const RequestPtr &req, ThreadContext *tc, BaseTLB::Mode mode)
Definition: lsq_impl.hh:768
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
transferNeedsBurst
bool transferNeedsBurst(Addr addr, unsigned int size, unsigned int block_size)
Returns true if the given memory access (address, size) needs to be fragmented across aligned fixed-s...
Definition: utils.hh:77
LSQ::numFreeLoadEntries
unsigned numFreeLoadEntries()
Returns the number of free load entries.
Definition: lsq_impl.hh:424
LSQ::maxLQEntries
unsigned maxLQEntries
Max LQ Size - Used to Enforce Sharing Policies.
Definition: lsq.hh:1173
LSQ::LSQRequest::getVaddr
Addr getVaddr(int idx=0) const
Definition: lsq.hh:481
BaseTLB::Write
@ Write
Definition: tlb.hh:57
LSQ::setActiveThreads
void setActiveThreads(std::list< ThreadID > *at_ptr)
Sets the pointer to the list of active threads.
Definition: lsq_impl.hh:121
LSQ::LSQRequest::setState
void setState(const State &newState)
Definition: lsq.hh:275
LSQ::DcachePort::recvTimingSnoopReq
virtual void recvTimingSnoopReq(PacketPtr pkt)
Receive a timing snoop request from the peer.
Definition: lsq_impl.hh:1224
Packet::createWrite
static PacketPtr createWrite(const RequestPtr &req)
Definition: packet.hh:986
LSQ::LSQRequest::_fault
std::vector< Fault > _fault
Definition: lsq.hh:293
panic_if
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:197
LSQ::hasStoresToWB
bool hasStoresToWB()
Returns whether or not there are any stores to write back to memory.
Definition: lsq_impl.hh:629
LSQ::LSQRequest::_addr
const Addr _addr
Definition: lsq.hh:295
LSQ::LSQRequest
Memory operation metadata.
Definition: lsq.hh:230
LSQ::LSQRequest::squashTranslation
void squashTranslation()
Definition: lsq.hh:675
LSQ::SplitDataRequest::handleLocalAccess
virtual Cycles handleLocalAccess(ThreadContext *thread, PacketPtr pkt)
Memory mapped IPR accesses.
Definition: lsq_impl.hh:1151
LSQ::HtmCmdRequest::initiateTranslation
virtual void initiateTranslation()
Definition: lsq_impl.hh:1272
std
Overload hash function for BasicBlockRange type.
Definition: vec_reg.hh:587
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
addr
ip6_addr_t addr
Definition: inet.hh:423
LSQ::LSQRequest::numTranslatedFragments
uint32_t numTranslatedFragments
Definition: lsq.hh:277
LSQ::recvTimingSnoopReq
void recvTimingSnoopReq(PacketPtr pkt)
Definition: lsq_impl.hh:353
logging.hh
Cycles
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:83
LSQ::SingleDataRequest
Definition: lsq.hh:694
LSQ::sqFull
bool sqFull()
Returns if any of the SQs are full.
Definition: lsq_impl.hh:573
LSQ::LSQRequest::taskId
void taskId(const uint32_t &v)
Definition: lsq.hh:465
Packet::getPtr
T * getPtr()
get a pointer to the data ptr.
Definition: packet.hh:1157
LSQ::cacheBlocked
bool cacheBlocked() const
Is D-cache blocked?
Definition: lsq_impl.hh:182
LSQ::LSQRequest::_inst
const DynInstPtr _inst
Definition: lsq.hh:288
LSQ::SplitDataRequest::recvTimingResp
virtual bool recvTimingResp(PacketPtr pkt)
Definition: lsq_impl.hh:994
Complete
@ Complete
Definition: misc.hh:55
LSQ::SplitDataRequest
Definition: lsq.hh:775
LSQ::lsqPolicy
SMTQueuePolicy lsqPolicy
The LSQ policy for SMT mode.
Definition: lsq.hh:1139
Packet::senderState
SenderState * senderState
This packet's sender state.
Definition: packet.hh:508
LSQ::name
std::string name() const
Returns the name of the LSQ.
Definition: lsq_impl.hh:114
cpu.hh
std::list< ThreadID >
Stats::total
const FlagsType total
Print the total.
Definition: info.hh:49
lsq.hh
LSQ::SingleDataRequest::initiateTranslation
virtual void initiateTranslation()
Definition: lsq_impl.hh:850
LSQ::SplitDataRequest::isCacheBlockHit
virtual bool isCacheBlockHit(Addr blockAddr, Addr cacheBlockMask)
Caches may probe into the load-store queue to enforce memory ordering guarantees.
Definition: lsq_impl.hh:1194
LSQ::LSQRequest::_size
const uint32_t _size
Definition: lsq.hh:296
LSQ::HtmCmdRequest::HtmCmdRequest
HtmCmdRequest(LSQUnit *port, const DynInstPtr &inst, const Request::Flags &flags_)
Definition: lsq_impl.hh:1242
LSQ::SingleDataRequest::isCacheBlockHit
virtual bool isCacheBlockHit(Addr blockAddr, Addr cacheBlockMask)
Test if the request accesses a particular cache line.
Definition: lsq_impl.hh:1172
LSQ::DcachePort::recvReqRetry
virtual void recvReqRetry()
Handles doing a retry of the previous send.
Definition: lsq_impl.hh:1236
ArmISA::v
Bitfield< 28 > v
Definition: miscregs_types.hh:51
LSQ::dumpInsts
void dumpInsts() const
Debugging function to print out all instructions.
Definition: lsq_impl.hh:663
LSQ::cpu
O3CPU * cpu
The CPU pointer.
Definition: lsq.hh:1109
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:171
LSQ::numThreads
ThreadID numThreads
Number of Threads.
Definition: lsq.hh:1185
LSQ::LSQRequest::request
RequestPtr request(int idx=0)
Definition: lsq.hh:473
ArmISA::offset
Bitfield< 23, 0 > offset
Definition: types.hh:153

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