gem5  v22.0.0.1
base.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2012,2016-2017, 2019-2020 ARM Limited
3  * All rights reserved
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Copyright (c) 2002-2005 The Regents of The University of Michigan
15  * Copyright (c) 2011 Regents of the University of California
16  * Copyright (c) 2013 Advanced Micro Devices, Inc.
17  * Copyright (c) 2013 Mark D. Hill and David A. Wood
18  * All rights reserved.
19  *
20  * Redistribution and use in source and binary forms, with or without
21  * modification, are permitted provided that the following conditions are
22  * met: redistributions of source code must retain the above copyright
23  * notice, this list of conditions and the following disclaimer;
24  * redistributions in binary form must reproduce the above copyright
25  * notice, this list of conditions and the following disclaimer in the
26  * documentation and/or other materials provided with the distribution;
27  * neither the name of the copyright holders nor the names of its
28  * contributors may be used to endorse or promote products derived from
29  * this software without specific prior written permission.
30  *
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
36  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
37  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
38  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
39  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
41  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42  */
43 
44 #include "cpu/base.hh"
45 
46 #include <iostream>
47 #include <sstream>
48 #include <string>
49 
50 #include "arch/generic/tlb.hh"
51 #include "base/cprintf.hh"
52 #include "base/loader/symtab.hh"
53 #include "base/logging.hh"
54 #include "base/output.hh"
55 #include "base/trace.hh"
56 #include "cpu/checker/cpu.hh"
57 #include "cpu/thread_context.hh"
58 #include "debug/Mwait.hh"
59 #include "debug/SyscallVerbose.hh"
60 #include "debug/Thread.hh"
61 #include "mem/page_table.hh"
62 #include "params/BaseCPU.hh"
63 #include "sim/clocked_object.hh"
64 #include "sim/full_system.hh"
65 #include "sim/process.hh"
66 #include "sim/root.hh"
67 #include "sim/sim_events.hh"
68 #include "sim/sim_exit.hh"
69 #include "sim/system.hh"
70 
71 // Hack
72 #include "sim/stat_control.hh"
73 
74 namespace gem5
75 {
76 
77 std::unique_ptr<BaseCPU::GlobalStats> BaseCPU::globalStats;
78 
79 std::vector<BaseCPU *> BaseCPU::cpuList;
80 
81 // This variable reflects the max number of threads in any CPU. Be
82 // careful to only use it once all the CPUs that you care about have
83 // been initialized
85 
86 CPUProgressEvent::CPUProgressEvent(BaseCPU *_cpu, Tick ival)
87  : Event(Event::Progress_Event_Pri), _interval(ival), lastNumInst(0),
88  cpu(_cpu), _repeatEvent(true)
89 {
90  if (_interval)
91  cpu->schedule(this, curTick() + _interval);
92 }
93 
94 void
95 CPUProgressEvent::process()
96 {
97  Counter temp = cpu->totalOps();
98 
99  if (_repeatEvent)
100  cpu->schedule(this, curTick() + _interval);
101 
102  if (cpu->switchedOut()) {
103  return;
104  }
105 
106 #ifndef NDEBUG
107  double ipc = double(temp - lastNumInst) / (_interval / cpu->clockPeriod());
108 
109  DPRINTFN("%s progress event, total committed:%i, progress insts committed: "
110  "%lli, IPC: %0.8d\n", cpu->name(), temp, temp - lastNumInst,
111  ipc);
112  ipc = 0.0;
113 #else
114  cprintf("%lli: %s progress event, total committed:%i, progress insts "
115  "committed: %lli\n", curTick(), cpu->name(), temp,
116  temp - lastNumInst);
117 #endif
118  lastNumInst = temp;
119 }
120 
121 const char *
122 CPUProgressEvent::description() const
123 {
124  return "CPU Progress";
125 }
126 
127 BaseCPU::BaseCPU(const Params &p, bool is_checker)
128  : ClockedObject(p), instCnt(0), _cpuId(p.cpu_id), _socketId(p.socket_id),
129  _instRequestorId(p.system->getRequestorId(this, "inst")),
130  _dataRequestorId(p.system->getRequestorId(this, "data")),
131  _taskId(context_switch_task_id::Unknown), _pid(invldPid),
132  _switchedOut(p.switched_out), _cacheLineSize(p.system->cacheLineSize()),
133  interrupts(p.interrupts), numThreads(p.numThreads), system(p.system),
134  previousCycle(0), previousState(CPU_STATE_SLEEP),
135  functionTraceStream(nullptr), currentFunctionStart(0),
136  currentFunctionEnd(0), functionEntryTick(0),
137  baseStats(this),
138  addressMonitor(p.numThreads),
139  syscallRetryLatency(p.syscallRetryLatency),
140  pwrGatingLatency(p.pwr_gating_latency),
141  powerGatingOnIdle(p.power_gating_on_idle),
142  enterPwrGatingEvent([this]{ enterPwrGating(); }, name())
143 {
144  // if Python did not provide a valid ID, do it here
145  if (_cpuId == -1 ) {
146  _cpuId = cpuList.size();
147  }
148 
149  // add self to global list of CPUs
150  cpuList.push_back(this);
151 
152  DPRINTF(SyscallVerbose, "Constructing CPU with id %d, socket id %d\n",
153  _cpuId, _socketId);
154 
155  if (numThreads > maxThreadsPerCPU)
156  maxThreadsPerCPU = numThreads;
157 
158  functionTracingEnabled = false;
159  if (p.function_trace) {
160  const std::string fname = csprintf("ftrace.%s", name());
161  functionTraceStream = simout.findOrCreate(fname)->stream();
162 
163  currentFunctionStart = currentFunctionEnd = 0;
164  functionEntryTick = p.function_trace_start;
165 
166  if (p.function_trace_start == 0) {
167  functionTracingEnabled = true;
168  } else {
169  Event *event = new EventFunctionWrapper(
170  [this]{ enableFunctionTrace(); }, name(), true);
171  schedule(event, p.function_trace_start);
172  }
173  }
174 
175  tracer = params().tracer;
176 
177  if (params().isa.size() != numThreads) {
178  fatal("Number of ISAs (%i) assigned to the CPU does not equal number "
179  "of threads (%i).\n", params().isa.size(), numThreads);
180  }
181 }
182 
183 void
184 BaseCPU::enableFunctionTrace()
185 {
186  functionTracingEnabled = true;
187 }
188 
189 BaseCPU::~BaseCPU()
190 {
191 }
192 
193 void
194 BaseCPU::postInterrupt(ThreadID tid, int int_num, int index)
195 {
196  interrupts[tid]->post(int_num, index);
197  // Only wake up syscall emulation if it is not waiting on a futex.
198  // This is to model the fact that instructions such as ARM SEV
199  // should wake up a WFE sleep, but not a futex syscall WAIT.
200  if (FullSystem || !system->futexMap.is_waiting(threadContexts[tid]))
201  wakeup(tid);
202 }
203 
204 void
205 BaseCPU::armMonitor(ThreadID tid, Addr address)
206 {
207  assert(tid < numThreads);
208  AddressMonitor &monitor = addressMonitor[tid];
209 
210  monitor.armed = true;
211  monitor.vAddr = address;
212  monitor.pAddr = 0x0;
213  DPRINTF(Mwait, "[tid:%d] Armed monitor (vAddr=0x%lx)\n", tid, address);
214 }
215 
216 bool
217 BaseCPU::mwait(ThreadID tid, PacketPtr pkt)
218 {
219  assert(tid < numThreads);
220  AddressMonitor &monitor = addressMonitor[tid];
221 
222  if (!monitor.gotWakeup) {
223  int block_size = cacheLineSize();
224  uint64_t mask = ~((uint64_t)(block_size - 1));
225 
226  assert(pkt->req->hasPaddr());
227  monitor.pAddr = pkt->getAddr() & mask;
228  monitor.waiting = true;
229 
230  DPRINTF(Mwait, "[tid:%d] mwait called (vAddr=0x%lx, "
231  "line's paddr=0x%lx)\n", tid, monitor.vAddr, monitor.pAddr);
232  return true;
233  } else {
234  monitor.gotWakeup = false;
235  return false;
236  }
237 }
238 
239 void
240 BaseCPU::mwaitAtomic(ThreadID tid, ThreadContext *tc, BaseMMU *mmu)
241 {
242  assert(tid < numThreads);
243  AddressMonitor &monitor = addressMonitor[tid];
244 
245  RequestPtr req = std::make_shared<Request>();
246 
247  Addr addr = monitor.vAddr;
248  int block_size = cacheLineSize();
249  uint64_t mask = ~((uint64_t)(block_size - 1));
250  int size = block_size;
251 
252  //The address of the next line if it crosses a cache line boundary.
253  Addr secondAddr = roundDown(addr + size - 1, block_size);
254 
255  if (secondAddr > addr)
256  size = secondAddr - addr;
257 
258  req->setVirt(addr, size, 0x0, dataRequestorId(),
259  tc->pcState().instAddr());
260 
261  // translate to physical address
262  Fault fault = mmu->translateAtomic(req, tc, BaseMMU::Read);
263  assert(fault == NoFault);
264 
265  monitor.pAddr = req->getPaddr() & mask;
266  monitor.waiting = true;
267 
268  DPRINTF(Mwait, "[tid:%d] mwait called (vAddr=0x%lx, line's paddr=0x%lx)\n",
269  tid, monitor.vAddr, monitor.pAddr);
270 }
271 
272 void
274 {
275  // Set up instruction-count-based termination events, if any. This needs
276  // to happen after threadContexts has been constructed.
277  if (params().max_insts_any_thread != 0) {
278  const char *cause = "a thread reached the max instruction count";
279  for (ThreadID tid = 0; tid < numThreads; ++tid)
280  scheduleInstStop(tid, params().max_insts_any_thread, cause);
281  }
282 
283  // Set up instruction-count-based termination events for SimPoints
284  // Typically, there are more than one action points.
285  // Simulation.py is responsible to take the necessary actions upon
286  // exitting the simulation loop.
287  if (!params().simpoint_start_insts.empty()) {
288  const char *cause = "simpoint starting point found";
289  for (size_t i = 0; i < params().simpoint_start_insts.size(); ++i)
290  scheduleInstStop(0, params().simpoint_start_insts[i], cause);
291  }
292 
293  if (params().max_insts_all_threads != 0) {
294  const char *cause = "all threads reached the max instruction count";
295 
296  // allocate & initialize shared downcounter: each event will
297  // decrement this when triggered; simulation will terminate
298  // when counter reaches 0
299  int *counter = new int;
300  *counter = numThreads;
301  for (ThreadID tid = 0; tid < numThreads; ++tid) {
302  Event *event = new CountedExitEvent(cause, *counter);
303  threadContexts[tid]->scheduleInstCountEvent(
304  event, params().max_insts_all_threads);
305  }
306  }
307 
308  if (!params().switched_out) {
309  registerThreadContexts();
310 
311  verifyMemoryMode();
312  }
313 }
314 
315 void
316 BaseCPU::startup()
317 {
318  if (params().progress_interval) {
319  new CPUProgressEvent(this, params().progress_interval);
320  }
321 
322  if (_switchedOut)
323  powerState->set(enums::PwrState::OFF);
324 
325  // Assumption CPU start to operate instantaneously without any latency
326  if (powerState->get() == enums::PwrState::UNDEFINED)
327  powerState->set(enums::PwrState::ON);
328 
329 }
330 
332 BaseCPU::pmuProbePoint(const char *name)
333 {
334  probing::PMUUPtr ptr;
335  ptr.reset(new probing::PMU(getProbeManager(), name));
336 
337  return ptr;
338 }
339 
340 void
341 BaseCPU::regProbePoints()
342 {
343  ppAllCycles = pmuProbePoint("Cycles");
344  ppActiveCycles = pmuProbePoint("ActiveCycles");
345 
346  ppRetiredInsts = pmuProbePoint("RetiredInsts");
347  ppRetiredInstsPC = pmuProbePoint("RetiredInstsPC");
348  ppRetiredLoads = pmuProbePoint("RetiredLoads");
349  ppRetiredStores = pmuProbePoint("RetiredStores");
350  ppRetiredBranches = pmuProbePoint("RetiredBranches");
351 
352  ppSleeping = new ProbePointArg<bool>(this->getProbeManager(),
353  "Sleeping");
354 }
355 
356 void
357 BaseCPU::probeInstCommit(const StaticInstPtr &inst, Addr pc)
358 {
359  if (!inst->isMicroop() || inst->isLastMicroop()) {
360  ppRetiredInsts->notify(1);
361  ppRetiredInstsPC->notify(pc);
362  }
363 
364  if (inst->isLoad())
365  ppRetiredLoads->notify(1);
366 
367  if (inst->isStore() || inst->isAtomic())
368  ppRetiredStores->notify(1);
369 
370  if (inst->isControl())
371  ppRetiredBranches->notify(1);
372 }
373 
374 BaseCPU::
375 BaseCPUStats::BaseCPUStats(statistics::Group *parent)
376  : statistics::Group(parent),
377  ADD_STAT(numCycles, statistics::units::Cycle::get(),
378  "Number of cpu cycles simulated"),
379  ADD_STAT(numWorkItemsStarted, statistics::units::Count::get(),
380  "Number of work items this cpu started"),
381  ADD_STAT(numWorkItemsCompleted, statistics::units::Count::get(),
382  "Number of work items this cpu completed")
383 {
384 }
385 
386 void
387 BaseCPU::regStats()
388 {
389  ClockedObject::regStats();
390 
391  if (!globalStats) {
392  /* We need to construct the global CPU stat structure here
393  * since it needs a pointer to the Root object. */
394  globalStats.reset(new GlobalStats(Root::root()));
395  }
396 
397  using namespace statistics;
398 
399  int size = threadContexts.size();
400  if (size > 1) {
401  for (int i = 0; i < size; ++i) {
402  std::stringstream namestr;
403  ccprintf(namestr, "%s.ctx%d", name(), i);
404  threadContexts[i]->regStats(namestr.str());
405  }
406  } else if (size == 1)
407  threadContexts[0]->regStats(name());
408 }
409 
410 Port &
411 BaseCPU::getPort(const std::string &if_name, PortID idx)
412 {
413  // Get the right port based on name. This applies to all the
414  // subclasses of the base CPU and relies on their implementation
415  // of getDataPort and getInstPort.
416  if (if_name == "dcache_port")
417  return getDataPort();
418  else if (if_name == "icache_port")
419  return getInstPort();
420  else
421  return ClockedObject::getPort(if_name, idx);
422 }
423 
424 void
425 BaseCPU::registerThreadContexts()
426 {
427  assert(system->multiThread || numThreads == 1);
428 
429  fatal_if(interrupts.size() != numThreads,
430  "CPU %s has %i interrupt controllers, but is expecting one "
431  "per thread (%i)\n",
432  name(), interrupts.size(), numThreads);
433 
434  for (ThreadID tid = 0; tid < threadContexts.size(); ++tid) {
435  ThreadContext *tc = threadContexts[tid];
436 
437  system->registerThreadContext(tc);
438 
439  if (!FullSystem)
440  tc->getProcessPtr()->assignThreadContext(tc->contextId());
441 
442  interrupts[tid]->setThreadContext(tc);
443  tc->getIsaPtr()->setThreadContext(tc);
444  }
445 }
446 
447 void
448 BaseCPU::deschedulePowerGatingEvent()
449 {
450  if (enterPwrGatingEvent.scheduled()){
451  deschedule(enterPwrGatingEvent);
452  }
453 }
454 
455 void
456 BaseCPU::schedulePowerGatingEvent()
457 {
458  for (auto tc : threadContexts) {
459  if (tc->status() == ThreadContext::Active)
460  return;
461  }
462 
463  if (powerState->get() == enums::PwrState::CLK_GATED &&
464  powerGatingOnIdle) {
465  assert(!enterPwrGatingEvent.scheduled());
466  // Schedule a power gating event when clock gated for the specified
467  // amount of time
468  schedule(enterPwrGatingEvent, clockEdge(pwrGatingLatency));
469  }
470 }
471 
472 int
473 BaseCPU::findContext(ThreadContext *tc)
474 {
475  ThreadID size = threadContexts.size();
476  for (ThreadID tid = 0; tid < size; ++tid) {
477  if (tc == threadContexts[tid])
478  return tid;
479  }
480  return 0;
481 }
482 
483 void
484 BaseCPU::activateContext(ThreadID thread_num)
485 {
486  DPRINTF(Thread, "activate contextId %d\n",
487  threadContexts[thread_num]->contextId());
488  // Squash enter power gating event while cpu gets activated
489  if (enterPwrGatingEvent.scheduled())
490  deschedule(enterPwrGatingEvent);
491  // For any active thread running, update CPU power state to active (ON)
492  powerState->set(enums::PwrState::ON);
493 
494  updateCycleCounters(CPU_STATE_WAKEUP);
495 }
496 
497 void
498 BaseCPU::suspendContext(ThreadID thread_num)
499 {
500  DPRINTF(Thread, "suspend contextId %d\n",
501  threadContexts[thread_num]->contextId());
502  // Check if all threads are suspended
503  for (auto t : threadContexts) {
504  if (t->status() != ThreadContext::Suspended) {
505  return;
506  }
507  }
508 
509  // All CPU thread are suspended, update cycle count
510  updateCycleCounters(CPU_STATE_SLEEP);
511 
512  // All CPU threads suspended, enter lower power state for the CPU
513  powerState->set(enums::PwrState::CLK_GATED);
514 
515  // If pwrGatingLatency is set to 0 then this mechanism is disabled
516  if (powerGatingOnIdle) {
517  // Schedule power gating event when clock gated for pwrGatingLatency
518  // cycles
519  schedule(enterPwrGatingEvent, clockEdge(pwrGatingLatency));
520  }
521 }
522 
523 void
524 BaseCPU::haltContext(ThreadID thread_num)
525 {
526  updateCycleCounters(BaseCPU::CPU_STATE_SLEEP);
527 }
528 
529 void
530 BaseCPU::enterPwrGating(void)
531 {
532  powerState->set(enums::PwrState::OFF);
533 }
534 
535 void
536 BaseCPU::switchOut()
537 {
538  assert(!_switchedOut);
539  _switchedOut = true;
540 
541  // Flush all TLBs in the CPU to avoid having stale translations if
542  // it gets switched in later.
543  flushTLBs();
544 
545  // Go to the power gating state
546  powerState->set(enums::PwrState::OFF);
547 }
548 
549 void
550 BaseCPU::takeOverFrom(BaseCPU *oldCPU)
551 {
552  assert(threadContexts.size() == oldCPU->threadContexts.size());
553  assert(_cpuId == oldCPU->cpuId());
554  assert(_switchedOut);
555  assert(oldCPU != this);
556  _pid = oldCPU->getPid();
557  _taskId = oldCPU->taskId();
558  // Take over the power state of the switchedOut CPU
559  powerState->set(oldCPU->powerState->get());
560 
561  previousState = oldCPU->previousState;
562  previousCycle = oldCPU->previousCycle;
563 
564  _switchedOut = false;
565 
566  ThreadID size = threadContexts.size();
567  for (ThreadID i = 0; i < size; ++i) {
568  ThreadContext *newTC = threadContexts[i];
569  ThreadContext *oldTC = oldCPU->threadContexts[i];
570 
571  newTC->getIsaPtr()->setThreadContext(newTC);
572 
573  newTC->takeOverFrom(oldTC);
574 
575  assert(newTC->contextId() == oldTC->contextId());
576  assert(newTC->threadId() == oldTC->threadId());
577  system->replaceThreadContext(newTC, newTC->contextId());
578 
579  /* This code no longer works since the zero register (e.g.,
580  * r31 on Alpha) doesn't necessarily contain zero at this
581  * point.
582  if (debug::Context)
583  ThreadContext::compare(oldTC, newTC);
584  */
585 
586  newTC->getMMUPtr()->takeOverFrom(oldTC->getMMUPtr());
587 
588  // Checker whether or not we have to transfer CheckerCPU
589  // objects over in the switch
590  CheckerCPU *old_checker = oldTC->getCheckerCpuPtr();
591  CheckerCPU *new_checker = newTC->getCheckerCpuPtr();
592  if (old_checker && new_checker) {
593  new_checker->getMMUPtr()->takeOverFrom(old_checker->getMMUPtr());
594  }
595  }
596 
597  interrupts = oldCPU->interrupts;
598  for (ThreadID tid = 0; tid < numThreads; tid++) {
599  interrupts[tid]->setThreadContext(threadContexts[tid]);
600  }
601  oldCPU->interrupts.clear();
602 
603  // All CPUs have an instruction and a data port, and the new CPU's
604  // ports are dangling while the old CPU has its ports connected
605  // already. Unbind the old CPU and then bind the ports of the one
606  // we are switching to.
607  getInstPort().takeOverFrom(&oldCPU->getInstPort());
608  getDataPort().takeOverFrom(&oldCPU->getDataPort());
609 }
610 
611 void
612 BaseCPU::flushTLBs()
613 {
614  for (ThreadID i = 0; i < threadContexts.size(); ++i) {
615  ThreadContext &tc(*threadContexts[i]);
616  CheckerCPU *checker(tc.getCheckerCpuPtr());
617 
618  tc.getMMUPtr()->flushAll();
619  if (checker) {
620  checker->getMMUPtr()->flushAll();
621  }
622  }
623 }
624 
625 void
627 {
628  SERIALIZE_SCALAR(instCnt);
629 
630  if (!_switchedOut) {
631  /* Unlike _pid, _taskId is not serialized, as they are dynamically
632  * assigned unique ids that are only meaningful for the duration of
633  * a specific run. We will need to serialize the entire taskMap in
634  * system. */
635  SERIALIZE_SCALAR(_pid);
636 
637  // Serialize the threads, this is done by the CPU implementation.
638  for (ThreadID i = 0; i < numThreads; ++i) {
639  ScopedCheckpointSection sec(cp, csprintf("xc.%i", i));
640  interrupts[i]->serialize(cp);
641  serializeThread(cp, i);
642  }
643  }
644 }
645 
646 void
647 BaseCPU::unserialize(CheckpointIn &cp)
648 {
649  UNSERIALIZE_SCALAR(instCnt);
650 
651  if (!_switchedOut) {
652  UNSERIALIZE_SCALAR(_pid);
653 
654  // Unserialize the threads, this is done by the CPU implementation.
655  for (ThreadID i = 0; i < numThreads; ++i) {
656  ScopedCheckpointSection sec(cp, csprintf("xc.%i", i));
657  interrupts[i]->unserialize(cp);
658  unserializeThread(cp, i);
659  }
660  }
661 }
662 
663 void
664 BaseCPU::scheduleInstStop(ThreadID tid, Counter insts, const char *cause)
665 {
666  const Tick now(getCurrentInstCount(tid));
667  Event *event(new LocalSimLoopExitEvent(cause, 0));
668 
669  threadContexts[tid]->scheduleInstCountEvent(event, now + insts);
670 }
671 
672 Tick
673 BaseCPU::getCurrentInstCount(ThreadID tid)
674 {
675  return threadContexts[tid]->getCurrentInstCount();
676 }
677 
678 AddressMonitor::AddressMonitor()
679 {
680  armed = false;
681  waiting = false;
682  gotWakeup = false;
683 }
684 
685 bool
686 AddressMonitor::doMonitor(PacketPtr pkt)
687 {
688  assert(pkt->req->hasPaddr());
689  if (armed && waiting) {
690  if (pAddr == pkt->getAddr()) {
691  DPRINTF(Mwait, "pAddr=0x%lx invalidated: waking up core\n",
692  pkt->getAddr());
693  waiting = false;
694  return true;
695  }
696  }
697  return false;
698 }
699 
700 
701 void
702 BaseCPU::traceFunctionsInternal(Addr pc)
703 {
704  if (loader::debugSymbolTable.empty())
705  return;
706 
707  // if pc enters different function, print new function symbol and
708  // update saved range. Otherwise do nothing.
709  if (pc < currentFunctionStart || pc >= currentFunctionEnd) {
711  pc, currentFunctionEnd);
712 
713  std::string sym_str;
714  if (it == loader::debugSymbolTable.end()) {
715  // no symbol found: use addr as label
716  sym_str = csprintf("%#x", pc);
717  currentFunctionStart = pc;
718  currentFunctionEnd = pc + 1;
719  } else {
720  sym_str = it->name;
721  currentFunctionStart = it->address;
722  }
723 
724  ccprintf(*functionTraceStream, " (%d)\n%d: %s",
725  curTick() - functionEntryTick, curTick(), sym_str);
726  functionEntryTick = curTick();
727  }
728 }
729 
730 
731 BaseCPU::GlobalStats::GlobalStats(statistics::Group *parent)
732  : statistics::Group(parent),
733  ADD_STAT(simInsts, statistics::units::Count::get(),
734  "Number of instructions simulated"),
735  ADD_STAT(simOps, statistics::units::Count::get(),
736  "Number of ops (including micro ops) simulated"),
737  ADD_STAT(hostInstRate, statistics::units::Rate<
738  statistics::units::Count, statistics::units::Second>::get(),
739  "Simulator instruction rate (inst/s)"),
740  ADD_STAT(hostOpRate, statistics::units::Rate<
741  statistics::units::Count, statistics::units::Second>::get(),
742  "Simulator op (including micro ops) rate (op/s)")
743 {
744  simInsts
745  .functor(BaseCPU::numSimulatedInsts)
746  .precision(0)
747  .prereq(simInsts)
748  ;
749 
750  simOps
751  .functor(BaseCPU::numSimulatedOps)
752  .precision(0)
753  .prereq(simOps)
754  ;
755 
756  hostInstRate
757  .precision(0)
758  .prereq(simInsts)
759  ;
760 
761  hostOpRate
762  .precision(0)
763  .prereq(simOps)
764  ;
765 
766  hostInstRate = simInsts / hostSeconds;
767  hostOpRate = simOps / hostSeconds;
768 }
769 
770 } // namespace gem5
gem5::curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
fatal
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:190
gem5::PortID
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:245
gem5::unserialize
void unserialize(ThreadContext &tc, CheckpointIn &cp)
Definition: thread_context.cc:264
gem5::maxThreadsPerCPU
int maxThreadsPerCPU
The maximum number of active threads across all cpus.
Definition: base.cc:84
gem5::NoFault
constexpr decltype(nullptr) NoFault
Definition: types.hh:253
gem5::cprintf
void cprintf(const char *format, const Args &...args)
Definition: cprintf.hh:155
system.hh
UNSERIALIZE_SCALAR
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:575
gem5::MipsISA::index
Bitfield< 30, 0 > index
Definition: pra_constants.hh:47
sim_events.hh
gem5::MipsISA::event
Bitfield< 10, 5 > event
Definition: pra_constants.hh:300
tlb.hh
gem5::simout
OutputDirectory simout
Definition: output.cc:62
gem5::X86ISA::system
Bitfield< 15 > system
Definition: misc.hh:997
std::vector
STL vector class.
Definition: stl.hh:37
gem5::csprintf
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:161
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:67
sim_exit.hh
gem5::OutputDirectory::findOrCreate
OutputStream * findOrCreate(const std::string &name, bool binary=false)
Definition: output.cc:262
output.hh
gem5::ccprintf
void ccprintf(cp::Print &print)
Definition: cprintf.hh:130
root.hh
gem5::takeOverFrom
void takeOverFrom(ThreadContext &ntc, ThreadContext &otc)
Copy state between thread contexts in preparation for CPU handover.
Definition: thread_context.cc:312
gem5::PacketPtr
Packet * PacketPtr
Definition: thread_context.hh:76
gem5::OutputStream::stream
std::ostream * stream() const
Get the output underlying output stream.
Definition: output.hh:62
gem5::StaticInstPtr
RefCountingPtr< StaticInst > StaticInstPtr
Definition: static_inst_fwd.hh:37
gem5::VegaISA::t
Bitfield< 51 > t
Definition: pagetable.hh:56
gem5::Fault
std::shared_ptr< FaultBase > Fault
Definition: types.hh:248
gem5::VegaISA::p
Bitfield< 54 > p
Definition: pagetable.hh:70
gem5::probing::PMUUPtr
std::unique_ptr< PMU > PMUUPtr
Definition: pmu.hh:61
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:186
gem5::Event
Definition: eventq.hh:251
ADD_STAT
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition: group.hh:75
gem5::Tick
uint64_t Tick
Tick count type.
Definition: types.hh:58
cpu.hh
gem5::RequestPtr
std::shared_ptr< Request > RequestPtr
Definition: request.hh:92
process.hh
gem5::loader::SymbolTable::findNearest
const_iterator findNearest(Addr addr, Addr &next_addr) const
Find the nearest symbol equal to or less than the supplied address (e.g., the label for the enclosing...
Definition: symtab.hh:361
gem5::ArmISA::mask
Bitfield< 3, 0 > mask
Definition: pcstate.hh:63
cprintf.hh
gem5::roundDown
static constexpr T roundDown(const T &val, const U &align)
This function is used to align addresses in memory.
Definition: intmath.hh:279
gem5::serialize
void serialize(const ThreadContext &tc, CheckpointOut &cp)
Thread context serialization helpers.
Definition: thread_context.cc:215
gem5::Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
name
const std::string & name()
Definition: trace.cc:49
SERIALIZE_SCALAR
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:568
full_system.hh
gem5::FullSystem
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
Definition: root.cc:220
stat_control.hh
gem5::context_switch_task_id::Unknown
@ Unknown
Definition: request.hh:85
base.hh
clocked_object.hh
gem5::MipsISA::pc
Bitfield< 4 > pc
Definition: pra_constants.hh:243
gem5::statistics::Counter
double Counter
All counters are of 64-bit values.
Definition: types.hh:47
logging.hh
gem5::CheckpointOut
std::ostream CheckpointOut
Definition: serialize.hh:66
gem5::statistics::init
const FlagsType init
This Stat is Initialized.
Definition: info.hh:56
trace.hh
symtab.hh
DPRINTFN
#define DPRINTFN(...)
Definition: trace.hh:214
gem5::loader::debugSymbolTable
SymbolTable debugSymbolTable
Global unified debugging symbol table (for target).
Definition: symtab.cc:44
gem5::RiscvISA::OFF
@ OFF
Definition: isa.hh:62
fatal_if
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:226
page_table.hh
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: gpu_translation_state.hh:37
gem5::hostSeconds
statistics::Value & hostSeconds
Definition: stats.cc:48
thread_context.hh
gem5::ThreadID
int16_t ThreadID
Thread index/ID type.
Definition: types.hh:235
gem5::probing::PMU
ProbePointArg< uint64_t > PMU
PMU probe point.
Definition: pmu.hh:60
gem5::X86ISA::addr
Bitfield< 3 > addr
Definition: types.hh:84

Generated on Sat Jun 18 2022 08:12:19 for gem5 by doxygen 1.8.17