gem5  v20.0.0.3
timing.cc
Go to the documentation of this file.
1 /*
2  * Copyright 2014 Google, Inc.
3  * Copyright (c) 2010-2013,2015,2017-2018 ARM Limited
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) 2002-2005 The Regents of The University of Michigan
16  * All rights reserved.
17  *
18  * Redistribution and use in source and binary forms, with or without
19  * modification, are permitted provided that the following conditions are
20  * met: redistributions of source code must retain the above copyright
21  * notice, this list of conditions and the following disclaimer;
22  * redistributions in binary form must reproduce the above copyright
23  * notice, this list of conditions and the following disclaimer in the
24  * documentation and/or other materials provided with the distribution;
25  * neither the name of the copyright holders nor the names of its
26  * contributors may be used to endorse or promote products derived from
27  * this software without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40  */
41 
42 #include "cpu/simple/timing.hh"
43 
44 #include "arch/locked_mem.hh"
45 #include "arch/utility.hh"
46 #include "config/the_isa.hh"
47 #include "cpu/exetrace.hh"
48 #include "debug/Config.hh"
49 #include "debug/Drain.hh"
50 #include "debug/ExecFaulting.hh"
51 #include "debug/Mwait.hh"
52 #include "debug/SimpleCPU.hh"
53 #include "mem/packet.hh"
54 #include "mem/packet_access.hh"
55 #include "params/TimingSimpleCPU.hh"
56 #include "sim/faults.hh"
57 #include "sim/full_system.hh"
58 #include "sim/system.hh"
59 
60 using namespace std;
61 using namespace TheISA;
62 
63 void
65 {
67 }
68 
69 void
71 {
72  pkt = _pkt;
73  cpu->schedule(this, t);
74 }
75 
76 TimingSimpleCPU::TimingSimpleCPU(TimingSimpleCPUParams *p)
77  : BaseSimpleCPU(p), fetchTranslation(this), icachePort(this),
78  dcachePort(this), ifetch_pkt(NULL), dcache_pkt(NULL), previousCycle(0),
79  fetchEvent([this]{ fetch(); }, name())
80 {
81  _status = Idle;
82 }
83 
84 
85 
87 {
88 }
89 
92 {
93  // Deschedule any power gating event (if any)
95 
96  if (switchedOut())
97  return DrainState::Drained;
98 
99  if (_status == Idle ||
101  DPRINTF(Drain, "No need to drain.\n");
102  activeThreads.clear();
103  return DrainState::Drained;
104  } else {
105  DPRINTF(Drain, "Requesting drain.\n");
106 
107  // The fetch event can become descheduled if a drain didn't
108  // succeed on the first attempt. We need to reschedule it if
109  // the CPU is waiting for a microcode routine to complete.
112 
113  return DrainState::Draining;
114  }
115 }
116 
117 void
119 {
120  assert(!fetchEvent.scheduled());
121  if (switchedOut())
122  return;
123 
124  DPRINTF(SimpleCPU, "Resume\n");
126 
127  assert(!threadContexts.empty());
128 
130 
131  for (ThreadID tid = 0; tid < numThreads; tid++) {
132  if (threadInfo[tid]->thread->status() == ThreadContext::Active) {
133  threadInfo[tid]->notIdleFraction = 1;
134 
135  activeThreads.push_back(tid);
136 
137  _status = BaseSimpleCPU::Running;
138 
139  // Fetch if any threads active
140  if (!fetchEvent.scheduled()) {
142  }
143  } else {
144  threadInfo[tid]->notIdleFraction = 0;
145  }
146  }
147 
148  // Reschedule any power gating event (if any)
150 
151  system->totalNumInsts = 0;
152 }
153 
154 bool
156 {
158  return false;
159 
160  DPRINTF(Drain, "tryCompleteDrain.\n");
161  if (!isCpuDrained())
162  return false;
163 
164  DPRINTF(Drain, "CPU done draining, processing drain event\n");
165  signalDrainDone();
166 
167  return true;
168 }
169 
170 void
172 {
174  M5_VAR_USED SimpleThread* thread = t_info.thread;
175 
177 
178  assert(!fetchEvent.scheduled());
179  assert(_status == BaseSimpleCPU::Running || _status == Idle);
180  assert(!t_info.stayAtPC);
181  assert(thread->microPC() == 0);
182 
185 }
186 
187 
188 void
190 {
192 
194 }
195 
196 void
198 {
199  if (!system->isTimingMode()) {
200  fatal("The timing CPU requires the memory system to be in "
201  "'timing' mode.\n");
202  }
203 }
204 
205 void
207 {
208  DPRINTF(SimpleCPU, "ActivateContext %d\n", thread_num);
209 
210  assert(thread_num < numThreads);
211 
212  threadInfo[thread_num]->notIdleFraction = 1;
215 
216  // kick things off by initiating the fetch of the next instruction
217  if (!fetchEvent.scheduled())
219 
220  if (std::find(activeThreads.begin(), activeThreads.end(), thread_num)
221  == activeThreads.end()) {
222  activeThreads.push_back(thread_num);
223  }
224 
225  BaseCPU::activateContext(thread_num);
226 }
227 
228 
229 void
231 {
232  DPRINTF(SimpleCPU, "SuspendContext %d\n", thread_num);
233 
234  assert(thread_num < numThreads);
235  activeThreads.remove(thread_num);
236 
237  if (_status == Idle)
238  return;
239 
240  assert(_status == BaseSimpleCPU::Running);
241 
242  threadInfo[thread_num]->notIdleFraction = 0;
243 
244  if (activeThreads.empty()) {
245  _status = Idle;
246 
247  if (fetchEvent.scheduled()) {
249  }
250  }
251 
252  BaseCPU::suspendContext(thread_num);
253 }
254 
255 bool
257 {
259  SimpleThread* thread = t_info.thread;
260 
261  const RequestPtr &req = pkt->req;
262 
263  // We're about the issues a locked load, so tell the monitor
264  // to start caring about this address
265  if (pkt->isRead() && pkt->req->isLLSC()) {
266  TheISA::handleLockedRead(thread, pkt->req);
267  }
268  if (req->isLocalAccess()) {
269  Cycles delay = req->localAccessor(thread->getTC(), pkt);
270  new IprEvent(pkt, this, clockEdge(delay));
272  dcache_pkt = NULL;
273  } else if (!dcachePort.sendTimingReq(pkt)) {
275  dcache_pkt = pkt;
276  } else {
278  // memory system takes ownership of packet
279  dcache_pkt = NULL;
280  }
281  return dcache_pkt == NULL;
282 }
283 
284 void
285 TimingSimpleCPU::sendData(const RequestPtr &req, uint8_t *data, uint64_t *res,
286  bool read)
287 {
289  SimpleThread* thread = t_info.thread;
290 
291  PacketPtr pkt = buildPacket(req, read);
292  pkt->dataDynamic<uint8_t>(data);
293 
294  if (req->getFlags().isSet(Request::NO_ACCESS)) {
295  assert(!dcache_pkt);
296  pkt->makeResponse();
297  completeDataAccess(pkt);
298  } else if (read) {
299  handleReadPacket(pkt);
300  } else {
301  bool do_access = true; // flag to suppress cache access
302 
303  if (req->isLLSC()) {
304  do_access = TheISA::handleLockedWrite(thread, req, dcachePort.cacheBlockMask);
305  } else if (req->isCondSwap()) {
306  assert(res);
307  req->setExtraData(*res);
308  }
309 
310  if (do_access) {
311  dcache_pkt = pkt;
313  threadSnoop(pkt, curThread);
314  } else {
316  completeDataAccess(pkt);
317  }
318  }
319 }
320 
321 void
323  const RequestPtr &req, uint8_t *data, bool read)
324 {
325  PacketPtr pkt1, pkt2;
326  buildSplitPacket(pkt1, pkt2, req1, req2, req, data, read);
327  if (req->getFlags().isSet(Request::NO_ACCESS)) {
328  assert(!dcache_pkt);
329  pkt1->makeResponse();
330  completeDataAccess(pkt1);
331  } else if (read) {
332  SplitFragmentSenderState * send_state =
333  dynamic_cast<SplitFragmentSenderState *>(pkt1->senderState);
334  if (handleReadPacket(pkt1)) {
335  send_state->clearFromParent();
336  send_state = dynamic_cast<SplitFragmentSenderState *>(
337  pkt2->senderState);
338  if (handleReadPacket(pkt2)) {
339  send_state->clearFromParent();
340  }
341  }
342  } else {
343  dcache_pkt = pkt1;
344  SplitFragmentSenderState * send_state =
345  dynamic_cast<SplitFragmentSenderState *>(pkt1->senderState);
346  if (handleWritePacket()) {
347  send_state->clearFromParent();
348  dcache_pkt = pkt2;
349  send_state = dynamic_cast<SplitFragmentSenderState *>(
350  pkt2->senderState);
351  if (handleWritePacket()) {
352  send_state->clearFromParent();
353  }
354  }
355  }
356 }
357 
358 void
360 {
361  // fault may be NoFault in cases where a fault is suppressed,
362  // for instance prefetches.
365 
366  if (traceData) {
367  // Since there was a fault, we shouldn't trace this instruction.
368  delete traceData;
369  traceData = NULL;
370  }
371 
372  postExecute();
373 
374  advanceInst(fault);
375 }
376 
377 PacketPtr
379 {
380  return read ? Packet::createRead(req) : Packet::createWrite(req);
381 }
382 
383 void
385  const RequestPtr &req1, const RequestPtr &req2, const RequestPtr &req,
386  uint8_t *data, bool read)
387 {
388  pkt1 = pkt2 = NULL;
389 
390  assert(!req1->isLocalAccess() && !req2->isLocalAccess());
391 
392  if (req->getFlags().isSet(Request::NO_ACCESS)) {
393  pkt1 = buildPacket(req, read);
394  return;
395  }
396 
397  pkt1 = buildPacket(req1, read);
398  pkt2 = buildPacket(req2, read);
399 
400  PacketPtr pkt = new Packet(req, pkt1->cmd.responseCommand());
401 
402  pkt->dataDynamic<uint8_t>(data);
403  pkt1->dataStatic<uint8_t>(data);
404  pkt2->dataStatic<uint8_t>(data + req1->getSize());
405 
406  SplitMainSenderState * main_send_state = new SplitMainSenderState;
407  pkt->senderState = main_send_state;
408  main_send_state->fragments[0] = pkt1;
409  main_send_state->fragments[1] = pkt2;
410  main_send_state->outstanding = 2;
411  pkt1->senderState = new SplitFragmentSenderState(pkt, 0);
412  pkt2->senderState = new SplitFragmentSenderState(pkt, 1);
413 }
414 
415 Fault
417  Request::Flags flags,
418  const std::vector<bool>& byte_enable)
419 {
421  SimpleThread* thread = t_info.thread;
422 
423  Fault fault;
424  const Addr pc = thread->instAddr();
425  unsigned block_size = cacheLineSize();
427 
428  if (traceData)
429  traceData->setMem(addr, size, flags);
430 
431  RequestPtr req = std::make_shared<Request>(
432  addr, size, flags, dataMasterId(), pc, thread->contextId());
433  if (!byte_enable.empty()) {
434  req->setByteEnable(byte_enable);
435  }
436 
437  req->taskId(taskId());
438 
439  Addr split_addr = roundDown(addr + size - 1, block_size);
440  assert(split_addr <= addr || split_addr - addr < block_size);
441 
443  if (split_addr > addr) {
444  RequestPtr req1, req2;
445  assert(!req->isLLSC() && !req->isSwap());
446  req->splitOnVaddr(split_addr, req1, req2);
447 
448  WholeTranslationState *state =
449  new WholeTranslationState(req, req1, req2, new uint8_t[size],
450  NULL, mode);
452  new DataTranslation<TimingSimpleCPU *>(this, state, 0);
454  new DataTranslation<TimingSimpleCPU *>(this, state, 1);
455 
456  thread->dtb->translateTiming(req1, thread->getTC(), trans1, mode);
457  thread->dtb->translateTiming(req2, thread->getTC(), trans2, mode);
458  } else {
459  WholeTranslationState *state =
460  new WholeTranslationState(req, new uint8_t[size], NULL, mode);
462  = new DataTranslation<TimingSimpleCPU *>(this, state);
463  thread->dtb->translateTiming(req, thread->getTC(), translation, mode);
464  }
465 
466  return NoFault;
467 }
468 
469 bool
471 {
473  SimpleThread* thread = t_info.thread;
474 
475  const RequestPtr &req = dcache_pkt->req;
476  if (req->isLocalAccess()) {
477  Cycles delay = req->localAccessor(thread->getTC(), dcache_pkt);
478  new IprEvent(dcache_pkt, this, clockEdge(delay));
480  dcache_pkt = NULL;
481  } else if (!dcachePort.sendTimingReq(dcache_pkt)) {
483  } else {
485  // memory system takes ownership of packet
486  dcache_pkt = NULL;
487  }
488  return dcache_pkt == NULL;
489 }
490 
491 Fault
492 TimingSimpleCPU::writeMem(uint8_t *data, unsigned size,
493  Addr addr, Request::Flags flags, uint64_t *res,
494  const std::vector<bool>& byte_enable)
495 {
497  SimpleThread* thread = t_info.thread;
498 
499  uint8_t *newData = new uint8_t[size];
500  const Addr pc = thread->instAddr();
501  unsigned block_size = cacheLineSize();
503 
504  if (data == NULL) {
505  assert(flags & Request::STORE_NO_DATA);
506  // This must be a cache block cleaning request
507  memset(newData, 0, size);
508  } else {
509  memcpy(newData, data, size);
510  }
511 
512  if (traceData)
513  traceData->setMem(addr, size, flags);
514 
515  RequestPtr req = std::make_shared<Request>(
516  addr, size, flags, dataMasterId(), pc, thread->contextId());
517  if (!byte_enable.empty()) {
518  req->setByteEnable(byte_enable);
519  }
520 
521  req->taskId(taskId());
522 
523  Addr split_addr = roundDown(addr + size - 1, block_size);
524  assert(split_addr <= addr || split_addr - addr < block_size);
525 
527 
528  // TODO: TimingSimpleCPU doesn't support arbitrarily long multi-line mem.
529  // accesses yet
530 
531  if (split_addr > addr) {
532  RequestPtr req1, req2;
533  assert(!req->isLLSC() && !req->isSwap());
534  req->splitOnVaddr(split_addr, req1, req2);
535 
536  WholeTranslationState *state =
537  new WholeTranslationState(req, req1, req2, newData, res, mode);
539  new DataTranslation<TimingSimpleCPU *>(this, state, 0);
541  new DataTranslation<TimingSimpleCPU *>(this, state, 1);
542 
543  thread->dtb->translateTiming(req1, thread->getTC(), trans1, mode);
544  thread->dtb->translateTiming(req2, thread->getTC(), trans2, mode);
545  } else {
546  WholeTranslationState *state =
547  new WholeTranslationState(req, newData, res, mode);
549  new DataTranslation<TimingSimpleCPU *>(this, state);
550  thread->dtb->translateTiming(req, thread->getTC(), translation, mode);
551  }
552 
553  // Translation faults will be returned via finishTranslation()
554  return NoFault;
555 }
556 
557 Fault
559  Request::Flags flags,
560  AtomicOpFunctorPtr amo_op)
561 {
563  SimpleThread* thread = t_info.thread;
564 
565  Fault fault;
566  const Addr pc = thread->instAddr();
567  unsigned block_size = cacheLineSize();
569 
570  if (traceData)
571  traceData->setMem(addr, size, flags);
572 
573  RequestPtr req = make_shared<Request>(addr, size, flags,
574  dataMasterId(), pc, thread->contextId(),
575  std::move(amo_op));
576 
577  assert(req->hasAtomicOpFunctor());
578 
579  req->taskId(taskId());
580 
581  Addr split_addr = roundDown(addr + size - 1, block_size);
582 
583  // AMO requests that access across a cache line boundary are not
584  // allowed since the cache does not guarantee AMO ops to be executed
585  // atomically in two cache lines
586  // For ISAs such as x86 that requires AMO operations to work on
587  // accesses that cross cache-line boundaries, the cache needs to be
588  // modified to support locking both cache lines to guarantee the
589  // atomicity.
590  if (split_addr > addr) {
591  panic("AMO requests should not access across a cache line boundary\n");
592  }
593 
595 
596  WholeTranslationState *state =
597  new WholeTranslationState(req, new uint8_t[size], NULL, mode);
599  = new DataTranslation<TimingSimpleCPU *>(this, state);
600  thread->dtb->translateTiming(req, thread->getTC(), translation, mode);
601 
602  return NoFault;
603 }
604 
605 void
607 {
608  for (ThreadID tid = 0; tid < numThreads; tid++) {
609  if (tid != sender) {
610  if (getCpuAddrMonitor(tid)->doMonitor(pkt)) {
611  wakeup(tid);
612  }
613  TheISA::handleLockedSnoop(threadInfo[tid]->thread, pkt,
615  }
616  }
617 }
618 
619 void
621 {
623 
624  if (state->getFault() != NoFault) {
625  if (state->isPrefetch()) {
626  state->setNoFault();
627  }
628  delete [] state->data;
629  state->deleteReqs();
630  translationFault(state->getFault());
631  } else {
632  if (!state->isSplit) {
633  sendData(state->mainReq, state->data, state->res,
634  state->mode == BaseTLB::Read);
635  } else {
636  sendSplitData(state->sreqLow, state->sreqHigh, state->mainReq,
637  state->data, state->mode == BaseTLB::Read);
638  }
639  }
640 
641  delete state;
642 }
643 
644 
645 void
647 {
648  // Change thread if multi-threaded
650 
652  SimpleThread* thread = t_info.thread;
653 
654  DPRINTF(SimpleCPU, "Fetch\n");
655 
659  }
660 
661  // We must have just got suspended by a PC event
662  if (_status == Idle)
663  return;
664 
665  TheISA::PCState pcState = thread->pcState();
666  bool needToFetch = !isRomMicroPC(pcState.microPC()) &&
668 
669  if (needToFetch) {
671  RequestPtr ifetch_req = std::make_shared<Request>();
672  ifetch_req->taskId(taskId());
673  ifetch_req->setContext(thread->contextId());
674  setupFetchRequest(ifetch_req);
675  DPRINTF(SimpleCPU, "Translating address %#x\n", ifetch_req->getVaddr());
676  thread->itb->translateTiming(ifetch_req, thread->getTC(),
678  } else {
680  completeIfetch(NULL);
681 
684  }
685 }
686 
687 
688 void
689 TimingSimpleCPU::sendFetch(const Fault &fault, const RequestPtr &req,
690  ThreadContext *tc)
691 {
692  if (fault == NoFault) {
693  DPRINTF(SimpleCPU, "Sending fetch for addr %#x(pa: %#x)\n",
694  req->getVaddr(), req->getPaddr());
695  ifetch_pkt = new Packet(req, MemCmd::ReadReq);
696  ifetch_pkt->dataStatic(&inst);
697  DPRINTF(SimpleCPU, " -- pkt addr: %#x\n", ifetch_pkt->getAddr());
698 
699  if (!icachePort.sendTimingReq(ifetch_pkt)) {
700  // Need to wait for retry
702  } else {
703  // Need to wait for cache to respond
705  // ownership of packet transferred to memory system
706  ifetch_pkt = NULL;
707  }
708  } else {
709  DPRINTF(SimpleCPU, "Translation of addr %#x faulted\n", req->getVaddr());
710  // fetch fault: advance directly to next instruction (fault handler)
712  advanceInst(fault);
713  }
714 
717 }
718 
719 
720 void
722 {
724 
725  if (_status == Faulting)
726  return;
727 
728  if (fault != NoFault) {
729  DPRINTF(SimpleCPU, "Fault occured. Handling the fault\n");
730 
731  advancePC(fault);
732 
733  // A syscall fault could suspend this CPU (e.g., futex_wait)
734  // If the _status is not Idle, schedule an event to fetch the next
735  // instruction after 'stall' ticks.
736  // If the cpu has been suspended (i.e., _status == Idle), another
737  // cpu will wake this cpu up later.
738  if (_status != Idle) {
739  DPRINTF(SimpleCPU, "Scheduling fetch event after the Fault\n");
740 
741  Tick stall = dynamic_pointer_cast<SyscallRetryFault>(fault) ?
743  reschedule(fetchEvent, stall, true);
744  _status = Faulting;
745  }
746 
747  return;
748  }
749 
750  if (!t_info.stayAtPC)
751  advancePC(fault);
752 
753  if (tryCompleteDrain())
754  return;
755 
757  // kick off fetch of next instruction... callback from icache
758  // response will cause that instruction to be executed,
759  // keeping the CPU running.
760  fetch();
761  }
762 }
763 
764 
765 void
767 {
769 
770  DPRINTF(SimpleCPU, "Complete ICache Fetch for addr %#x\n", pkt ?
771  pkt->getAddr() : 0);
772 
773  // received a response from the icache: execute the received
774  // instruction
775  assert(!pkt || !pkt->isError());
776  assert(_status == IcacheWaitResponse);
777 
779 
782 
783  if (pkt)
784  pkt->req->setAccessLatency();
785 
786 
787  preExecute();
789  // load or store: just send to dcache
790  Fault fault = curStaticInst->initiateAcc(&t_info, traceData);
791 
792  // If we're not running now the instruction will complete in a dcache
793  // response callback or the instruction faulted and has started an
794  // ifetch
796  if (fault != NoFault && traceData) {
797  // If there was a fault, we shouldn't trace this instruction.
798  delete traceData;
799  traceData = NULL;
800  }
801 
802  postExecute();
803  // @todo remove me after debugging with legion done
804  if (curStaticInst && (!curStaticInst->isMicroop() ||
806  instCnt++;
807  advanceInst(fault);
808  }
809  } else if (curStaticInst) {
810  // non-memory instruction: execute completely now
811  Fault fault = curStaticInst->execute(&t_info, traceData);
812 
813  // keep an instruction count
814  if (fault == NoFault)
815  countInst();
816  else if (traceData && !DTRACE(ExecFaulting)) {
817  delete traceData;
818  traceData = NULL;
819  }
820 
821  postExecute();
822  // @todo remove me after debugging with legion done
823  if (curStaticInst && (!curStaticInst->isMicroop() ||
825  instCnt++;
826  advanceInst(fault);
827  } else {
829  }
830 
831  if (pkt) {
832  delete pkt;
833  }
834 }
835 
836 void
838 {
839  cpu->completeIfetch(pkt);
840 }
841 
842 bool
844 {
845  DPRINTF(SimpleCPU, "Received fetch response %#x\n", pkt->getAddr());
846  // we should only ever see one response per cycle since we only
847  // issue a new request once this response is sunk
848  assert(!tickEvent.scheduled());
849  // delay processing of returned data until next CPU clock edge
850  tickEvent.schedule(pkt, cpu->clockEdge());
851 
852  return true;
853 }
854 
855 void
857 {
858  // we shouldn't get a retry unless we have a packet that we're
859  // waiting to transmit
860  assert(cpu->ifetch_pkt != NULL);
861  assert(cpu->_status == IcacheRetry);
862  PacketPtr tmp = cpu->ifetch_pkt;
863  if (sendTimingReq(tmp)) {
864  cpu->_status = IcacheWaitResponse;
865  cpu->ifetch_pkt = NULL;
866  }
867 }
868 
869 void
871 {
872  // received a response from the dcache: complete the load or store
873  // instruction
874  assert(!pkt->isError());
876  pkt->req->getFlags().isSet(Request::NO_ACCESS));
877 
878  pkt->req->setAccessLatency();
879 
882 
883  if (pkt->senderState) {
884  SplitFragmentSenderState * send_state =
885  dynamic_cast<SplitFragmentSenderState *>(pkt->senderState);
886  assert(send_state);
887  delete pkt;
888  PacketPtr big_pkt = send_state->bigPkt;
889  delete send_state;
890 
891  SplitMainSenderState * main_send_state =
892  dynamic_cast<SplitMainSenderState *>(big_pkt->senderState);
893  assert(main_send_state);
894  // Record the fact that this packet is no longer outstanding.
895  assert(main_send_state->outstanding != 0);
896  main_send_state->outstanding--;
897 
898  if (main_send_state->outstanding) {
899  return;
900  } else {
901  delete main_send_state;
902  big_pkt->senderState = NULL;
903  pkt = big_pkt;
904  }
905  }
906 
908 
910  traceData);
911 
912  // keep an instruction count
913  if (fault == NoFault)
914  countInst();
915  else if (traceData) {
916  // If there was a fault, we shouldn't trace this instruction.
917  delete traceData;
918  traceData = NULL;
919  }
920 
921  delete pkt;
922 
923  postExecute();
924 
925  advanceInst(fault);
926 }
927 
928 void
930 {
931  const Cycles delta(curCycle() - previousCycle);
932 
933  numCycles += delta;
934 
936 }
937 
938 void
940 {
941  for (ThreadID tid = 0; tid < cpu->numThreads; tid++) {
942  if (cpu->getCpuAddrMonitor(tid)->doMonitor(pkt)) {
943  cpu->wakeup(tid);
944  }
945  }
946 
947  // Making it uniform across all CPUs:
948  // The CPUs need to be woken up only on an invalidation packet (when using caches)
949  // or on an incoming write packet (when not using caches)
950  // It is not necessary to wake up the processor on all incoming packets
951  if (pkt->isInvalidate() || pkt->isWrite()) {
952  for (auto &t_info : cpu->threadInfo) {
953  TheISA::handleLockedSnoop(t_info->thread, pkt, cacheBlockMask);
954  }
955  }
956 }
957 
958 void
960 {
961  for (ThreadID tid = 0; tid < cpu->numThreads; tid++) {
962  if (cpu->getCpuAddrMonitor(tid)->doMonitor(pkt)) {
963  cpu->wakeup(tid);
964  }
965  }
966 }
967 
968 bool
970 {
971  DPRINTF(SimpleCPU, "Received load/store response %#x\n", pkt->getAddr());
972 
973  // The timing CPU is not really ticked, instead it relies on the
974  // memory system (fetch and load/store) to set the pace.
975  if (!tickEvent.scheduled()) {
976  // Delay processing of returned data until next CPU clock edge
977  tickEvent.schedule(pkt, cpu->clockEdge());
978  return true;
979  } else {
980  // In the case of a split transaction and a cache that is
981  // faster than a CPU we could get two responses in the
982  // same tick, delay the second one
983  if (!retryRespEvent.scheduled())
984  cpu->schedule(retryRespEvent, cpu->clockEdge(Cycles(1)));
985  return false;
986  }
987 }
988 
989 void
991 {
992  cpu->completeDataAccess(pkt);
993 }
994 
995 void
997 {
998  // we shouldn't get a retry unless we have a packet that we're
999  // waiting to transmit
1000  assert(cpu->dcache_pkt != NULL);
1001  assert(cpu->_status == DcacheRetry);
1002  PacketPtr tmp = cpu->dcache_pkt;
1003  if (tmp->senderState) {
1004  // This is a packet from a split access.
1005  SplitFragmentSenderState * send_state =
1006  dynamic_cast<SplitFragmentSenderState *>(tmp->senderState);
1007  assert(send_state);
1008  PacketPtr big_pkt = send_state->bigPkt;
1009 
1010  SplitMainSenderState * main_send_state =
1011  dynamic_cast<SplitMainSenderState *>(big_pkt->senderState);
1012  assert(main_send_state);
1013 
1014  if (sendTimingReq(tmp)) {
1015  // If we were able to send without retrying, record that fact
1016  // and try sending the other fragment.
1017  send_state->clearFromParent();
1018  int other_index = main_send_state->getPendingFragment();
1019  if (other_index > 0) {
1020  tmp = main_send_state->fragments[other_index];
1021  cpu->dcache_pkt = tmp;
1022  if ((big_pkt->isRead() && cpu->handleReadPacket(tmp)) ||
1023  (big_pkt->isWrite() && cpu->handleWritePacket())) {
1024  main_send_state->fragments[other_index] = NULL;
1025  }
1026  } else {
1027  cpu->_status = DcacheWaitResponse;
1028  // memory system takes ownership of packet
1029  cpu->dcache_pkt = NULL;
1030  }
1031  }
1032  } else if (sendTimingReq(tmp)) {
1033  cpu->_status = DcacheWaitResponse;
1034  // memory system takes ownership of packet
1035  cpu->dcache_pkt = NULL;
1036  }
1037 }
1038 
1040  Tick t)
1041  : pkt(_pkt), cpu(_cpu)
1042 {
1043  cpu->schedule(this, t);
1044 }
1045 
1046 void
1048 {
1050 }
1051 
1052 const char *
1054 {
1055  return "Timing Simple CPU Delay IPR event";
1056 }
1057 
1058 
1059 void
1061 {
1062  dcachePort.printAddr(a);
1063 }
1064 
1065 
1067 //
1068 // TimingSimpleCPU Simulation Object
1069 //
1071 TimingSimpleCPUParams::create()
1072 {
1073  return new TimingSimpleCPU(this);
1074 }
StaticInstPtr curStaticInst
Definition: base.hh:103
uint32_t taskId() const
Get cpu task id.
Definition: base.hh:203
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:163
void advancePC(const Fault &fault)
Definition: base.cc:650
#define DPRINTF(x,...)
Definition: trace.hh:225
This class represents part of a data address translation.
Definition: translation.hh:215
virtual const char * description() const
Return a C string describing the event.
Definition: timing.cc:1053
std::list< ThreadID > activeThreads
Definition: base.hh:99
decltype(nullptr) constexpr NoFault
Definition: types.hh:243
PacketPtr dcache_pkt
Definition: timing.hh:258
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:81
AddressMonitor * getCpuAddrMonitor(ThreadID tid)
Definition: base.hh:610
BaseTLB * itb
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:171
void checkPcEventQueue()
Definition: base.cc:134
bool isDelayedCommit() const
Definition: static_inst.hh:200
DcachePort dcachePort
Definition: timing.hh:255
void switchOut() override
Prepare for another CPU to take over execution.
Definition: timing.cc:171
void schedule(PacketPtr _pkt, Tick t)
Definition: timing.cc:70
ThreadID numThreads
Number of threads we&#39;re actually simulating (<= SMT_MAX_THREADS).
Definition: base.hh:374
virtual bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the peer.
Definition: timing.cc:843
bool isCpuDrained() const
Check if a system is in a drained state.
Definition: timing.hh:351
Tick instCnt
Instruction count used for SPARC misc register.
Definition: base.hh:111
virtual Fault completeAcc(Packet *pkt, ExecContext *xc, Trace::InstRecord *traceData) const
Definition: static_inst.hh:284
void sendData(const RequestPtr &req, uint8_t *data, uint64_t *res, bool read)
Definition: timing.cc:285
std::shared_ptr< Request > RequestPtr
Definition: request.hh:81
Bitfield< 8 > a
void suspendContext(ThreadID thread_num) override
Notify the CPU that the indicated context is now suspended.
Definition: timing.cc:230
TheISA::MachInst inst
Current instruction.
Definition: base.hh:102
void deleteReqs()
Delete all requests that make up this translation.
Definition: translation.hh:194
ip6_addr_t addr
Definition: inet.hh:330
static PacketPtr createWrite(const RequestPtr &req)
Definition: packet.hh:913
std::unique_ptr< AtomicOpFunctor > AtomicOpFunctorPtr
Definition: amo.hh:228
ContextID contextId() const override
void wakeup(ThreadID tid) override
Definition: base.cc:425
virtual void activateContext(ThreadID thread_num)
Notify the CPU that the indicated context is now active.
Definition: base.cc:487
void verifyMemoryMode() const override
Verify that the system is in a memory mode supported by the CPU.
Definition: timing.cc:197
Fault initiateMemAMO(Addr addr, unsigned size, Request::Flags flags, AtomicOpFunctorPtr amo_op) override
Definition: timing.cc:558
TheISA::PCState pcState() const override
virtual Fault execute(ExecContext *xc, Trace::InstRecord *traceData) const =0
bool switchedOut() const
Determine if the CPU is switched out.
Definition: base.hh:363
The SimpleThread object provides a combination of the ThreadState object and the ThreadContext interf...
bool handleLockedWrite(XC *xc, const RequestPtr &req, Addr cacheBlockMask)
Definition: locked_mem.hh:77
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: timing.cc:64
void checkForInterrupts()
Definition: base.cc:436
Overload hash function for BasicBlockRange type.
Definition: vec_reg.hh:587
This class captures the state of an address translation.
Definition: translation.hh:58
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the slave port by calling its corresponding receive function...
Definition: port.hh:441
System * system
Definition: base.hh:382
ThreadID curThread
Definition: base.hh:83
void handleLockedRead(XC *xc, const RequestPtr &req)
Definition: locked_mem.hh:64
Bitfield< 4, 0 > mode
void preExecute()
Definition: base.cc:473
bool isWrite() const
Definition: packet.hh:523
bool isInvalidate() const
Definition: packet.hh:537
ThreadContext is the external interface to all thread state for anything outside of the CPU...
bool isRead() const
Definition: packet.hh:522
virtual Fault initiateAcc(ExecContext *xc, Trace::InstRecord *traceData) const
Definition: static_inst.hh:278
DrainState
Object drain/handover states.
Definition: drain.hh:71
void dataStatic(T *p)
Set the data pointer to the following value that should not be freed.
Definition: packet.hh:1034
Fault initiateMemRead(Addr addr, unsigned size, Request::Flags flags, const std::vector< bool > &byte_enable=std::vector< bool >()) override
Definition: timing.cc:416
void completeIfetch(PacketPtr)
Definition: timing.cc:766
bool isMemRef() const
Definition: static_inst.hh:160
RequestPtr req
A pointer to the original request.
Definition: packet.hh:321
void fetch()
Definition: timing.cc:646
DrainState drainState() const
Return the current drain state of an object.
Definition: drain.hh:308
void setupFetchRequest(const RequestPtr &req)
Definition: base.cc:456
void swapActiveThread()
Definition: base.cc:146
std::vector< ThreadContext * > threadContexts
Definition: base.hh:263
PacketPtr ifetch_pkt
Definition: timing.hh:257
bool tryCompleteDrain()
Try to complete a drain request.
Definition: timing.cc:155
void buildSplitPacket(PacketPtr &pkt1, PacketPtr &pkt2, const RequestPtr &req1, const RequestPtr &req2, const RequestPtr &req, uint8_t *data, bool read)
Definition: timing.cc:384
PacketPtr buildPacket(const RequestPtr &req, bool read)
Definition: timing.cc:378
Draining buffers pending serialization/handover.
Bitfield< 4 > pc
void countInst()
Definition: base.cc:162
bool isPrefetch() const
Check if this request is a prefetch.
Definition: translation.hh:169
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: base.cc:123
void schedulePowerGatingEvent()
Definition: base.cc:459
#define DTRACE(x)
Definition: trace.hh:223
void sendSplitData(const RequestPtr &req1, const RequestPtr &req2, const RequestPtr &req, uint8_t *data, bool read)
Definition: timing.cc:322
bool isError() const
Definition: packet.hh:549
virtual void takeOverFrom(BaseCPU *cpu)
Load the state of a CPU from the previous CPU object, invoked on all new CPUs that are about to be sw...
Definition: base.cc:555
MasterID dataMasterId() const
Reads this CPU&#39;s unique data requestor ID.
Definition: base.hh:185
uint64_t Tick
Tick count type.
Definition: types.hh:61
void updateCycleCounters(CPUState state)
base method keeping track of cycle progression
Definition: base.hh:528
bool handleReadPacket(PacketPtr pkt)
Definition: timing.cc:256
FetchTranslation fetchTranslation
Definition: timing.hh:131
void translationFault(const Fault &fault)
Definition: timing.cc:359
void takeOverFrom(BaseCPU *oldCPU) override
Load the state of a CPU from the previous CPU object, invoked on all new CPUs that are about to be sw...
Definition: timing.cc:189
virtual void translateTiming(const RequestPtr &req, ThreadContext *tc, Translation *translation, Mode mode)=0
void setMem(Addr a, Addr s, unsigned f)
Definition: insttracer.hh:169
void deschedule(Event &event)
Definition: eventq.hh:943
Fault writeMem(uint8_t *data, unsigned size, Addr addr, Request::Flags flags, uint64_t *res, const std::vector< bool > &byte_enable=std::vector< bool >()) override
Definition: timing.cc:492
Addr getAddr() const
Definition: packet.hh:720
Cycles syscallRetryLatency
Definition: base.hh:618
Cycles curCycle() const
Determine the current cycle, corresponding to a tick aligned to a clock edge.
virtual void recvFunctionalSnoop(PacketPtr pkt)
Receive a functional snoop request packet from the peer.
Definition: timing.cc:959
static const FlagsType STORE_NO_DATA
Definition: request.hh:196
void schedule(Event &event, Tick when)
Definition: eventq.hh:934
T roundDown(const T &val, const U &align)
This function is used to align addresses in memory.
Definition: intmath.hh:131
void sendFetch(const Fault &fault, const RequestPtr &req, ThreadContext *tc)
Definition: timing.cc:689
Status _status
Definition: base.hh:121
Tick nextCycle() const
Based on the clock of the object, determine the start tick of the first cycle that is at least one cy...
void reschedule(Event &event, Tick when, bool always=false)
Definition: eventq.hh:952
BaseTLB::Mode mode
Definition: translation.hh:72
StaticInstPtr curMacroStaticInst
Definition: base.hh:104
SimpleThread * thread
Definition: exec_context.hh:64
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:140
ThreadContext * getTC()
Returns the pointer to this SimpleThread&#39;s ThreadContext.
void printAddr(Addr a)
Inject a PrintReq for the given address to print the state of that address throughout the memory syst...
Definition: port.cc:95
static PacketPtr createRead(const RequestPtr &req)
Constructor-like methods that return Packets based on Request objects.
Definition: packet.hh:907
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:249
virtual void recvReqRetry()
Called by the peer if sendTimingReq was called on this peer (causing recvTimingReq to be called on th...
Definition: timing.cc:856
static bool isRomMicroPC(MicroPC upc)
Definition: types.hh:159
void threadSnoop(PacketPtr pkt, ThreadID sender)
Definition: timing.cc:606
Tick clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
EventFunctionWrapper fetchEvent
Definition: timing.hh:325
Addr instAddr() const override
bool isFirstMicroop() const
Definition: static_inst.hh:202
virtual void switchOut()
Prepare for another CPU to take over execution.
Definition: base.cc:539
void activateContext(ThreadID thread_num) override
Notify the CPU that the indicated context is now active.
Definition: timing.cc:206
Command responseCommand() const
Definition: packet.hh:225
virtual ~TimingSimpleCPU()
Definition: timing.cc:86
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:459
Mode
Definition: tlb.hh:57
int16_t ThreadID
Thread index/ID type.
Definition: types.hh:225
void makeResponse()
Take a request packet and modify it in place to be suitable for returning as a response to that reque...
Definition: packet.hh:931
virtual const std::string name() const
Definition: sim_object.hh:129
unsigned int cacheLineSize() const
Get the cache line size of the system.
Definition: base.hh:387
The request should not cause a memory access.
Definition: request.hh:134
Cycles previousCycle
Definition: timing.hh:260
virtual void recvReqRetry()
Called by the peer if sendTimingReq was called on this peer (causing recvTimingReq to be called on th...
Definition: timing.cc:996
Declaration of the Packet class.
Fault getFault() const
Determine whether this translation produced a fault.
Definition: translation.hh:133
Trace::InstRecord * traceData
Definition: base.hh:95
void deschedulePowerGatingEvent()
Definition: base.cc:451
IprEvent(Packet *_pkt, TimingSimpleCPU *_cpu, Tick t)
Definition: timing.cc:1039
SenderState * senderState
This packet&#39;s sender state.
Definition: packet.hh:474
MemCmd cmd
The command field of the packet.
Definition: packet.hh:316
void advanceInst(const Fault &fault)
Definition: timing.cc:721
virtual bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the peer.
Definition: timing.cc:969
Stats::Scalar numCycles
Definition: base.hh:599
std::vector< SimpleExecContext * > threadInfo
Definition: base.hh:98
void signalDrainDone() const
Signal that an object is drained.
Definition: drain.hh:289
IcachePort icachePort
Definition: timing.hh:254
void dataDynamic(T *p)
Set the data pointer to a value that should have delete [] called on it.
Definition: packet.hh:1072
void finishTranslation(WholeTranslationState *state)
Finish a DTB translation.
Definition: timing.cc:620
void handleLockedSnoop(XC *xc, PacketPtr pkt, Addr cacheBlockMask)
Definition: locked_mem.hh:58
void completeDataAccess(PacketPtr pkt)
Definition: timing.cc:870
void postExecute()
Definition: base.cc:561
void setNoFault()
Remove all faults from the translation.
Definition: translation.hh:147
TimingSimpleCPU * cpu
Definition: timing.hh:329
DrainState drain() override
Notify an object that it needs to drain its state.
Definition: timing.cc:91
TimingSimpleCPU(TimingSimpleCPUParams *params)
Definition: timing.cc:76
Bitfield< 5 > t
virtual void process()
Definition: timing.cc:1047
bool isTimingMode() const
Is the system in timing mode?
Definition: system.hh:142
void printAddr(Addr a)
Print state of address in memory system via PrintReq (for debugging).
Definition: timing.cc:1060
virtual void recvTimingSnoopReq(PacketPtr pkt)
Snoop a coherence request, we need to check if this causes a wakeup event on a cpu that is monitoring...
Definition: timing.cc:939
GenericISA::DelaySlotPCState< MachInst > PCState
Definition: types.hh:41
Bitfield< 0 > p
Running normally.
const char data[]
std::shared_ptr< FaultBase > Fault
Definition: types.hh:238
void drainResume() override
Resume execution after a successful drain.
Definition: timing.cc:118
bool isMicroop() const
Definition: static_inst.hh:199
bool handleWritePacket()
Definition: timing.cc:470
Counter totalNumInsts
Definition: system.hh:480
virtual void suspendContext(ThreadID thread_num)
Notify the CPU that the indicated context is now suspended.
Definition: base.cc:501
ProbePointArg< PacketInfo > Packet
Packet probe point.
Definition: mem.hh:103
void updateCycleCounts()
Definition: timing.cc:929
BaseTLB * dtb

Generated on Fri Jul 3 2020 15:53:01 for gem5 by doxygen 1.8.13