gem5  v21.0.1.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
trace_cpu.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 - 2016 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  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions are
16  * met: redistributions of source code must retain the above copyright
17  * notice, this list of conditions and the following disclaimer;
18  * redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in the
20  * documentation and/or other materials provided with the distribution;
21  * neither the name of the copyright holders nor the names of its
22  * contributors may be used to endorse or promote products derived from
23  * this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 #include "cpu/trace/trace_cpu.hh"
39 
40 #include "sim/sim_exit.hh"
41 
42 // Declare and initialize the static counter for number of trace CPUs.
44 
45 TraceCPU::TraceCPU(const TraceCPUParams &params)
46  : BaseCPU(params),
47  icachePort(this),
48  dcachePort(this),
49  instRequestorID(params.system->getRequestorId(this, "inst")),
50  dataRequestorID(params.system->getRequestorId(this, "data")),
51  instTraceFile(params.instTraceFile),
52  dataTraceFile(params.dataTraceFile),
53  icacheGen(*this, ".iside", icachePort, instRequestorID, instTraceFile),
54  dcacheGen(*this, ".dside", dcachePort, dataRequestorID, dataTraceFile,
55  params),
56  icacheNextEvent([this]{ schedIcacheNext(); }, name()),
57  dcacheNextEvent([this]{ schedDcacheNext(); }, name()),
58  oneTraceComplete(false),
59  traceOffset(0),
60  execCompleteEvent(nullptr),
61  enableEarlyExit(params.enableEarlyExit),
62  progressMsgInterval(params.progressMsgInterval),
63  progressMsgThreshold(params.progressMsgInterval), traceStats(this)
64 {
65  // Increment static counter for number of Trace CPUs.
67 
68  // Check that the python parameters for sizes of ROB, store buffer and
69  // load buffer do not overflow the corresponding C++ variables.
70  fatal_if(params.sizeROB > UINT16_MAX,
71  "ROB size set to %d exceeds the max. value of %d.",
72  params.sizeROB, UINT16_MAX);
73  fatal_if(params.sizeStoreBuffer > UINT16_MAX,
74  "ROB size set to %d exceeds the max. value of %d.",
75  params.sizeROB, UINT16_MAX);
76  fatal_if(params.sizeLoadBuffer > UINT16_MAX,
77  "Load buffer size set to %d exceeds the max. value of %d.",
78  params.sizeLoadBuffer, UINT16_MAX);
79 }
80 
81 void
82 TraceCPU::updateNumOps(uint64_t rob_num)
83 {
84  traceStats.numOps = rob_num;
85  if (progressMsgInterval != 0 &&
87  inform("%s: %i insts committed\n", name(), progressMsgThreshold);
89  }
90 }
91 
92 void
94 {
95  // Unbind the ports of the old CPU and bind the ports of the TraceCPU.
96  getInstPort().takeOverFrom(&oldCPU->getInstPort());
97  getDataPort().takeOverFrom(&oldCPU->getDataPort());
98 }
99 
100 void
102 {
103  DPRINTF(TraceCPUInst, "Instruction fetch request trace file is \"%s\".\n",
104  instTraceFile);
105  DPRINTF(TraceCPUData, "Data memory request trace file is \"%s\".\n",
106  dataTraceFile);
107 
108  BaseCPU::init();
109 
110  // Get the send tick of the first instruction read request
111  Tick first_icache_tick = icacheGen.init();
112 
113  // Get the send tick of the first data read/write request
114  Tick first_dcache_tick = dcacheGen.init();
115 
116  // Set the trace offset as the minimum of that in both traces
117  traceOffset = std::min(first_icache_tick, first_dcache_tick);
118  inform("%s: Time offset (tick) found as min of both traces is %lli.",
119  name(), traceOffset);
120 
121  // Schedule next icache and dcache event by subtracting the offset
122  schedule(icacheNextEvent, first_icache_tick - traceOffset);
123  schedule(dcacheNextEvent, first_dcache_tick - traceOffset);
124 
125  // Adjust the trace offset for the dcache generator's ready nodes
126  // We don't need to do this for the icache generator as it will
127  // send its first request at the first event and schedule subsequent
128  // events using a relative tick delta
130 
131  // If the Trace CPU simulation is configured to exit on any one trace
132  // completion then we don't need a counted event to count down all Trace
133  // CPUs in the system. If not then instantiate a counted event.
134  if (!enableEarlyExit) {
135  // The static counter for number of Trace CPUs is correctly set at
136  // this point so create an event and pass it.
137  execCompleteEvent = new CountedExitEvent("end of all traces reached.",
138  numTraceCPUs);
139  }
140 
141 }
142 
143 void
145 {
146  DPRINTF(TraceCPUInst, "IcacheGen event.\n");
147 
148  // Try to send the current packet or a retry packet if there is one
149  bool sched_next = icacheGen.tryNext();
150  // If packet sent successfully, schedule next event
151  if (sched_next) {
152  DPRINTF(TraceCPUInst,
153  "Scheduling next icacheGen event at %d.\n",
154  curTick() + icacheGen.tickDelta());
157  } else {
158  // check if traceComplete. If not, do nothing because sending failed
159  // and next event will be scheduled via RecvRetry()
160  if (icacheGen.isTraceComplete()) {
161  // If this is the first trace to complete, set the variable. If it
162  // is already set then both traces are complete to exit sim.
164  }
165  }
166  return;
167 }
168 
169 void
171 {
172  DPRINTF(TraceCPUData, "DcacheGen event.\n");
173 
174  // Update stat for numCycles
176 
177  dcacheGen.execute();
178  if (dcacheGen.isExecComplete()) {
180  }
181 }
182 
183 void
185 {
186  if (!oneTraceComplete) {
187  oneTraceComplete = true;
188  } else {
189  // Schedule event to indicate execution is complete as both
190  // instruction and data access traces have been played back.
191  inform("%s: Execution complete.", name());
192  // If the replay is configured to exit early, that is when any one
193  // execution is complete then exit immediately and return. Otherwise,
194  // schedule the counted exit that counts down completion of each Trace
195  // CPU.
196  if (enableEarlyExit) {
197  exitSimLoop("End of trace reached");
198  } else {
200  }
201  }
202 }
204  Stats::Group(trace),
205  ADD_STAT(numSchedDcacheEvent, UNIT_COUNT,
206  "Number of events scheduled to trigger data request generator"),
207  ADD_STAT(numSchedIcacheEvent, UNIT_COUNT,
208  "Number of events scheduled to trigger instruction request generator"),
209  ADD_STAT(numOps, UNIT_COUNT,
210  "Number of micro-ops simulated by the Trace CPU"),
211  ADD_STAT(cpi,
212  UNIT_RATE(Stats::Units::Cycle, Stats::Units::Count),
213  "Cycles per micro-op used as a proxy for CPI",
214  trace->baseStats.numCycles / numOps)
215 {
216  cpi.precision(6);
217 }
218 
221  const std::string& _name) :
222  Stats::Group(parent, _name.c_str()),
223  ADD_STAT(maxDependents, UNIT_COUNT,
224  "Max number of dependents observed on a node"),
225  ADD_STAT(maxReadyListSize, UNIT_COUNT,
226  "Max size of the ready list observed"),
227  ADD_STAT(numSendAttempted, UNIT_COUNT,
228  "Number of first attempts to send a request"),
229  ADD_STAT(numSendSucceeded, UNIT_COUNT,
230  "Number of successful first attempts"),
231  ADD_STAT(numSendFailed, UNIT_COUNT, "Number of failed first attempts"),
232  ADD_STAT(numRetrySucceeded, UNIT_COUNT, "Number of successful retries"),
233  ADD_STAT(numSplitReqs, UNIT_COUNT, "Number of split requests"),
234  ADD_STAT(numSOLoads, UNIT_COUNT, "Number of strictly ordered loads"),
235  ADD_STAT(numSOStores, UNIT_COUNT, "Number of strictly ordered stores"),
236  ADD_STAT(dataLastTick, UNIT_TICK,
237  "Last tick simulated from the elastic data trace")
238 {
239 }
240 
241 Tick
243 {
244  DPRINTF(TraceCPUData, "Initializing data memory request generator "
245  "DcacheGen: elastic issue with retry.\n");
246 
248  "Trace has %d elements. It must have at least %d elements.",
249  depGraph.size(), 2 * windowSize);
250  DPRINTF(TraceCPUData, "After 1st read, depGraph size:%d.\n",
251  depGraph.size());
252 
254  "Trace has %d elements. It must have at least %d elements.",
255  depGraph.size(), 2 * windowSize);
256  DPRINTF(TraceCPUData, "After 2st read, depGraph size:%d.\n",
257  depGraph.size());
258 
259  // Print readyList
260  if (DTRACE(TraceCPUData)) {
261  printReadyList();
262  }
263  auto free_itr = readyList.begin();
264  DPRINTF(TraceCPUData,
265  "Execute tick of the first dependency free node %lli is %d.\n",
266  free_itr->seqNum, free_itr->execTick);
267  // Return the execute tick of the earliest ready node so that an event
268  // can be scheduled to call execute()
269  return (free_itr->execTick);
270 }
271 
272 void
274 {
275  for (auto& free_node : readyList) {
276  free_node.execTick -= offset;
277  }
278 }
279 
280 void
282 {
283  trace.reset();
284 }
285 
286 bool
288 {
289  // Read and add next window
290  DPRINTF(TraceCPUData, "Reading next window from file.\n");
291 
292  if (traceComplete) {
293  // We are at the end of the file, thus we have no more records.
294  // Return false.
295  return false;
296  }
297 
298  DPRINTF(TraceCPUData, "Start read: Size of depGraph is %d.\n",
299  depGraph.size());
300 
301  uint32_t num_read = 0;
302  while (num_read != windowSize) {
303 
304  // Create a new graph node
305  GraphNode* new_node = new GraphNode;
306 
307  // Read the next line to get the next record. If that fails then end of
308  // trace has been reached and traceComplete needs to be set in addition
309  // to returning false.
310  if (!trace.read(new_node)) {
311  DPRINTF(TraceCPUData, "\tTrace complete!\n");
312  traceComplete = true;
313  return false;
314  }
315 
316  // Annotate the ROB dependencies of the new node onto the parent nodes.
317  addDepsOnParent(new_node, new_node->robDep);
318  // Annotate the register dependencies of the new node onto the parent
319  // nodes.
320  addDepsOnParent(new_node, new_node->regDep);
321 
322  num_read++;
323  // Add to map
324  depGraph[new_node->seqNum] = new_node;
325  if (new_node->robDep.empty() && new_node->regDep.empty()) {
326  // Source dependencies are already complete, check if resources
327  // are available and issue. The execution time is approximated
328  // to current time plus the computational delay.
329  checkAndIssue(new_node);
330  }
331  }
332 
333  DPRINTF(TraceCPUData, "End read: Size of depGraph is %d.\n",
334  depGraph.size());
335  return true;
336 }
337 
338 template<typename T>
339 void
341 {
342  auto dep_it = dep_list.begin();
343  while (dep_it != dep_list.end()) {
344  // We look up the valid dependency, i.e. the parent of this node
345  auto parent_itr = depGraph.find(*dep_it);
346  if (parent_itr != depGraph.end()) {
347  // If the parent is found, it is yet to be executed. Append a
348  // pointer to the new node to the dependents list of the parent
349  // node.
350  parent_itr->second->dependents.push_back(new_node);
351  auto num_depts = parent_itr->second->dependents.size();
352  elasticStats.maxDependents = std::max<double>(num_depts,
354  dep_it++;
355  } else {
356  // The dependency is not found in the graph. So consider
357  // the execution of the parent is complete, i.e. remove this
358  // dependency.
359  dep_it = dep_list.erase(dep_it);
360  }
361  }
362 }
363 
364 void
366 {
367  DPRINTF(TraceCPUData, "Execute start occupancy:\n");
368  DPRINTFR(TraceCPUData, "\tdepGraph = %d, readyList = %d, "
369  "depFreeQueue = %d ,", depGraph.size(), readyList.size(),
370  depFreeQueue.size());
372 
373  // Read next window to make sure that dependents of all dep-free nodes
374  // are in the depGraph
375  if (nextRead) {
376  readNextWindow();
377  nextRead = false;
378  }
379 
380  // First attempt to issue the pending dependency-free nodes held
381  // in depFreeQueue. If resources have become available for a node,
382  // then issue it, i.e. add the node to readyList.
383  while (!depFreeQueue.empty()) {
384  if (checkAndIssue(depFreeQueue.front(), false)) {
385  DPRINTF(TraceCPUData,
386  "Removing from depFreeQueue: seq. num %lli.\n",
387  (depFreeQueue.front())->seqNum);
388  depFreeQueue.pop();
389  } else {
390  break;
391  }
392  }
393  // Proceed to execute from readyList
394  auto graph_itr = depGraph.begin();
395  auto free_itr = readyList.begin();
396  // Iterate through readyList until the next free node has its execute
397  // tick later than curTick or the end of readyList is reached
398  while (free_itr->execTick <= curTick() && free_itr != readyList.end()) {
399 
400  // Get pointer to the node to be executed
401  graph_itr = depGraph.find(free_itr->seqNum);
402  assert(graph_itr != depGraph.end());
403  GraphNode* node_ptr = graph_itr->second;
404 
405  // If there is a retryPkt send that else execute the load
406  if (retryPkt) {
407  // The retryPkt must be the request that was created by the
408  // first node in the readyList.
409  if (retryPkt->req->getReqInstSeqNum() != node_ptr->seqNum) {
410  panic("Retry packet's seqence number does not match "
411  "the first node in the readyList.\n");
412  }
413  if (port.sendTimingReq(retryPkt)) {
415  retryPkt = nullptr;
416  }
417  } else if (node_ptr->isLoad() || node_ptr->isStore()) {
418  // If there is no retryPkt, attempt to send a memory request in
419  // case of a load or store node. If the send fails, executeMemReq()
420  // returns a packet pointer, which we save in retryPkt. In case of
421  // a comp node we don't do anything and simply continue as if the
422  // execution of the comp node succedded.
423  retryPkt = executeMemReq(node_ptr);
424  }
425  // If the retryPkt or a new load/store node failed, we exit from here
426  // as a retry from cache will bring the control to execute(). The
427  // first node in readyList then, will be the failed node.
428  if (retryPkt) {
429  break;
430  }
431 
432  // Proceed to remove dependencies for the successfully executed node.
433  // If it is a load which is not strictly ordered and we sent a
434  // request for it successfully, we do not yet mark any register
435  // dependencies complete. But as per dependency modelling we need
436  // to mark ROB dependencies of load and non load/store nodes which
437  // are based on successful sending of the load as complete.
438  if (node_ptr->isLoad() && !node_ptr->isStrictlyOrdered()) {
439  // If execute succeeded mark its dependents as complete
440  DPRINTF(TraceCPUData,
441  "Node seq. num %lli sent. Waking up dependents..\n",
442  node_ptr->seqNum);
443 
444  auto child_itr = (node_ptr->dependents).begin();
445  while (child_itr != (node_ptr->dependents).end()) {
446  // ROB dependency of a store on a load must not be removed
447  // after load is sent but after response is received
448  if (!(*child_itr)->isStore() &&
449  (*child_itr)->removeRobDep(node_ptr->seqNum)) {
450 
451  // Check if the child node has become dependency free
452  if ((*child_itr)->robDep.empty() &&
453  (*child_itr)->regDep.empty()) {
454 
455  // Source dependencies are complete, check if
456  // resources are available and issue
457  checkAndIssue(*child_itr);
458  }
459  // Remove this child for the sent load and point to new
460  // location of the element following the erased element
461  child_itr = node_ptr->dependents.erase(child_itr);
462  } else {
463  // This child is not dependency-free, point to the next
464  // child
465  child_itr++;
466  }
467  }
468  } else {
469  // If it is a strictly ordered load mark its dependents as complete
470  // as we do not send a request for this case. If it is a store or a
471  // comp node we also mark all its dependents complete.
472  DPRINTF(TraceCPUData, "Node seq. num %lli done. Waking"
473  " up dependents..\n", node_ptr->seqNum);
474 
475  for (auto child : node_ptr->dependents) {
476  // If the child node is dependency free removeDepOnInst()
477  // returns true.
478  if (child->removeDepOnInst(node_ptr->seqNum)) {
479  // Source dependencies are complete, check if resources
480  // are available and issue
481  checkAndIssue(child);
482  }
483  }
484  }
485 
486  // After executing the node, remove from readyList and delete node.
487  readyList.erase(free_itr);
488  // If it is a cacheable load which was sent, don't delete
489  // just yet. Delete it in completeMemAccess() after the
490  // response is received. If it is an strictly ordered
491  // load, it was not sent and all dependencies were simply
492  // marked complete. Thus it is safe to delete it. For
493  // stores and non load/store nodes all dependencies were
494  // marked complete so it is safe to delete it.
495  if (!node_ptr->isLoad() || node_ptr->isStrictlyOrdered()) {
496  // Release all resources occupied by the completed node
497  hwResource.release(node_ptr);
498  // clear the dynamically allocated set of dependents
499  (node_ptr->dependents).clear();
500  // Update the stat for numOps simulated
501  owner.updateNumOps(node_ptr->robNum);
502  // delete node
503  delete node_ptr;
504  // remove from graph
505  depGraph.erase(graph_itr);
506  }
507  // Point to first node to continue to next iteration of while loop
508  free_itr = readyList.begin();
509  } // end of while loop
510 
511  // Print readyList, sizes of queues and resource status after updating
512  if (DTRACE(TraceCPUData)) {
513  printReadyList();
514  DPRINTF(TraceCPUData, "Execute end occupancy:\n");
515  DPRINTFR(TraceCPUData, "\tdepGraph = %d, readyList = %d, "
516  "depFreeQueue = %d ,", depGraph.size(), readyList.size(),
517  depFreeQueue.size());
519  }
520 
521  if (retryPkt) {
522  DPRINTF(TraceCPUData, "Not scheduling an event as expecting a retry"
523  "event from the cache for seq. num %lli.\n",
524  retryPkt->req->getReqInstSeqNum());
525  return;
526  }
527  // If the size of the dependency graph is less than the dependency window
528  // then read from the trace file to populate the graph next time we are in
529  // execute.
530  if (depGraph.size() < windowSize && !traceComplete)
531  nextRead = true;
532 
533  // If cache is not blocked, schedule an event for the first execTick in
534  // readyList else retry from cache will schedule the event. If the ready
535  // list is empty then check if the next pending node has resources
536  // available to issue. If yes, then schedule an event for the next cycle.
537  if (!readyList.empty()) {
538  Tick next_event_tick = std::max(readyList.begin()->execTick,
539  curTick());
540  DPRINTF(TraceCPUData, "Attempting to schedule @%lli.\n",
541  next_event_tick);
542  owner.schedDcacheNextEvent(next_event_tick);
543  } else if (readyList.empty() && !depFreeQueue.empty() &&
545  DPRINTF(TraceCPUData, "Attempting to schedule @%lli.\n",
546  owner.clockEdge(Cycles(1)));
548  }
549 
550  // If trace is completely read, readyList is empty and depGraph is empty,
551  // set execComplete to true
552  if (depGraph.empty() && readyList.empty() && traceComplete &&
554  DPRINTF(TraceCPUData, "\tExecution Complete!\n");
555  execComplete = true;
557  }
558 }
559 
560 PacketPtr
562 {
563  DPRINTF(TraceCPUData, "Executing memory request %lli (phys addr %d, "
564  "virt addr %d, pc %#x, size %d, flags %d).\n",
565  node_ptr->seqNum, node_ptr->physAddr, node_ptr->virtAddr,
566  node_ptr->pc, node_ptr->size, node_ptr->flags);
567 
568  // If the request is strictly ordered, do not send it. Just return nullptr
569  // as if it was succesfully sent.
570  if (node_ptr->isStrictlyOrdered()) {
571  node_ptr->isLoad() ? ++elasticStats.numSOLoads :
573  DPRINTF(TraceCPUData, "Skipping strictly ordered request %lli.\n",
574  node_ptr->seqNum);
575  return nullptr;
576  }
577 
578  // Check if the request spans two cache lines as this condition triggers
579  // an assert fail in the L1 cache. If it does then truncate the size to
580  // access only until the end of that line and ignore the remainder. The
581  // stat counting this is useful to keep a check on how frequently this
582  // happens. If required the code could be revised to mimick splitting such
583  // a request into two.
584  unsigned blk_size = owner.cacheLineSize();
585  Addr blk_offset = (node_ptr->physAddr & (Addr)(blk_size - 1));
586  if (!(blk_offset + node_ptr->size <= blk_size)) {
587  node_ptr->size = blk_size - blk_offset;
589  }
590 
591  // Create a request and the packet containing request
592  auto req = std::make_shared<Request>(
593  node_ptr->physAddr, node_ptr->size, node_ptr->flags, requestorId);
594  req->setReqInstSeqNum(node_ptr->seqNum);
595 
596  // If this is not done it triggers assert in L1 cache for invalid contextId
597  req->setContext(ContextID(0));
598 
599  req->setPC(node_ptr->pc);
600  // If virtual address is valid, set the virtual address field
601  // of the request.
602  if (node_ptr->virtAddr != 0) {
603  req->setVirt(node_ptr->virtAddr, node_ptr->size,
604  node_ptr->flags, requestorId, node_ptr->pc);
605  req->setPaddr(node_ptr->physAddr);
606  req->setReqInstSeqNum(node_ptr->seqNum);
607  }
608 
609  PacketPtr pkt;
610  uint8_t* pkt_data = new uint8_t[req->getSize()];
611  if (node_ptr->isLoad()) {
612  pkt = Packet::createRead(req);
613  } else {
614  pkt = Packet::createWrite(req);
615  memset(pkt_data, 0xA, req->getSize());
616  }
617  pkt->dataDynamic(pkt_data);
618 
619  // Call RequestPort method to send a timing request for this packet
620  bool success = port.sendTimingReq(pkt);
622 
623  if (!success) {
624  // If it fails, return the packet to retry when a retry is signalled by
625  // the cache
627  DPRINTF(TraceCPUData, "Send failed. Saving packet for retry.\n");
628  return pkt;
629  } else {
630  // It is succeeds, return nullptr
632  return nullptr;
633  }
634 }
635 
636 bool
638 {
639  // Assert the node is dependency-free
640  assert(node_ptr->robDep.empty() && node_ptr->regDep.empty());
641 
642  // If this is the first attempt, print a debug message to indicate this.
643  if (first) {
644  DPRINTFR(TraceCPUData, "\t\tseq. num %lli(%s) with rob num %lli is now"
645  " dependency free.\n", node_ptr->seqNum, node_ptr->typeToStr(),
646  node_ptr->robNum);
647  }
648 
649  // Check if resources are available to issue the specific node
650  if (hwResource.isAvailable(node_ptr)) {
651  // If resources are free only then add to readyList
652  DPRINTFR(TraceCPUData, "\t\tResources available for seq. num %lli. "
653  "Adding to readyList, occupying resources.\n",
654  node_ptr->seqNum);
655  // Compute the execute tick by adding the compute delay for the node
656  // and add the ready node to the ready list
657  addToSortedReadyList(node_ptr->seqNum,
658  owner.clockEdge() + node_ptr->compDelay);
659  // Account for the resources taken up by this issued node.
660  hwResource.occupy(node_ptr);
661  return true;
662  } else {
663  if (first) {
664  // Although dependencies are complete, resources are not available.
665  DPRINTFR(TraceCPUData, "\t\tResources unavailable for seq. num "
666  "%lli. Adding to depFreeQueue.\n", node_ptr->seqNum);
667  depFreeQueue.push(node_ptr);
668  } else {
669  DPRINTFR(TraceCPUData, "\t\tResources unavailable for seq. num "
670  "%lli. Still pending issue.\n", node_ptr->seqNum);
671  }
672  return false;
673  }
674 }
675 
676 void
678 {
679  // Release the resources for this completed node.
680  if (pkt->isWrite()) {
681  // Consider store complete.
683  // If it is a store response then do nothing since we do not model
684  // dependencies on store completion in the trace. But if we were
685  // blocking execution due to store buffer fullness, we need to schedule
686  // an event and attempt to progress.
687  } else {
688  // If it is a load response then release the dependents waiting on it.
689  // Get pointer to the completed load
690  auto graph_itr = depGraph.find(pkt->req->getReqInstSeqNum());
691  assert(graph_itr != depGraph.end());
692  GraphNode* node_ptr = graph_itr->second;
693 
694  // Release resources occupied by the load
695  hwResource.release(node_ptr);
696 
697  DPRINTF(TraceCPUData, "Load seq. num %lli response received. Waking up"
698  " dependents..\n", node_ptr->seqNum);
699 
700  for (auto child : node_ptr->dependents) {
701  if (child->removeDepOnInst(node_ptr->seqNum)) {
702  checkAndIssue(child);
703  }
704  }
705 
706  // clear the dynamically allocated set of dependents
707  (node_ptr->dependents).clear();
708  // Update the stat for numOps completed
709  owner.updateNumOps(node_ptr->robNum);
710  // delete node
711  delete node_ptr;
712  // remove from graph
713  depGraph.erase(graph_itr);
714  }
715 
716  if (DTRACE(TraceCPUData)) {
717  printReadyList();
718  }
719 
720  // If the size of the dependency graph is less than the dependency window
721  // then read from the trace file to populate the graph next time we are in
722  // execute.
723  if (depGraph.size() < windowSize && !traceComplete)
724  nextRead = true;
725 
726  // If not waiting for retry, attempt to schedule next event
727  if (!retryPkt) {
728  // We might have new dep-free nodes in the list which will have execute
729  // tick greater than or equal to curTick. But a new dep-free node might
730  // have its execute tick earlier. Therefore, attempt to reschedule. It
731  // could happen that the readyList is empty and we got here via a
732  // last remaining response. So, either the trace is complete or there
733  // are pending nodes in the depFreeQueue. The checking is done in the
734  // execute() control flow, so schedule an event to go via that flow.
735  Tick next_event_tick = readyList.empty() ? owner.clockEdge(Cycles(1)) :
736  std::max(readyList.begin()->execTick, owner.clockEdge(Cycles(1)));
737  DPRINTF(TraceCPUData, "Attempting to schedule @%lli.\n",
738  next_event_tick);
739  owner.schedDcacheNextEvent(next_event_tick);
740  }
741 }
742 
743 void
745  Tick exec_tick)
746 {
747  ReadyNode ready_node;
748  ready_node.seqNum = seq_num;
749  ready_node.execTick = exec_tick;
750 
751  // Iterator to readyList
752  auto itr = readyList.begin();
753 
754  // If the readyList is empty, simply insert the new node at the beginning
755  // and return
756  if (itr == readyList.end()) {
757  readyList.insert(itr, ready_node);
759  std::max<double>(readyList.size(),
761  return;
762  }
763 
764  // If the new node has its execution tick equal to the first node in the
765  // list then go to the next node. If the first node in the list failed
766  // to execute, its position as the first is thus maintained.
767  if (retryPkt) {
768  if (retryPkt->req->getReqInstSeqNum() == itr->seqNum)
769  itr++;
770  }
771 
772  // Increment the iterator and compare the node pointed to by it to the new
773  // node till the position to insert the new node is found.
774  bool found = false;
775  while (!found && itr != readyList.end()) {
776  // If the execution tick of the new node is less than the node then
777  // this is the position to insert
778  if (exec_tick < itr->execTick) {
779  found = true;
780  // If the execution tick of the new node is equal to the node then
781  // sort in ascending order of sequence numbers
782  } else if (exec_tick == itr->execTick) {
783  // If the sequence number of the new node is less than the node
784  // then this is the position to insert
785  if (seq_num < itr->seqNum) {
786  found = true;
787  // Else go to next node
788  } else {
789  itr++;
790  }
791  } else {
792  // If the execution tick of the new node is greater than the node
793  // then go to the next node.
794  itr++;
795  }
796  }
797  readyList.insert(itr, ready_node);
798  // Update the stat for max size reached of the readyList
799  elasticStats.maxReadyListSize = std::max<double>(readyList.size(),
801 }
802 
803 void
805 {
806  auto itr = readyList.begin();
807  if (itr == readyList.end()) {
808  DPRINTF(TraceCPUData, "readyList is empty.\n");
809  return;
810  }
811  DPRINTF(TraceCPUData, "Printing readyList:\n");
812  while (itr != readyList.end()) {
813  auto graph_itr = depGraph.find(itr->seqNum);
814  M5_VAR_USED GraphNode* node_ptr = graph_itr->second;
815  DPRINTFR(TraceCPUData, "\t%lld(%s), %lld\n", itr->seqNum,
816  node_ptr->typeToStr(), itr->execTick);
817  itr++;
818  }
819 }
820 
822  uint16_t max_rob, uint16_t max_stores, uint16_t max_loads) :
823  sizeROB(max_rob),
824  sizeStoreBuffer(max_stores),
825  sizeLoadBuffer(max_loads),
826  oldestInFlightRobNum(UINT64_MAX),
827  numInFlightLoads(0),
828  numInFlightStores(0)
829 {}
830 
831 void
833 {
834  // Occupy ROB entry for the issued node
835  // Merely maintain the oldest node, i.e. numerically least robNum by saving
836  // it in the variable oldestInFLightRobNum.
837  inFlightNodes[new_node->seqNum] = new_node->robNum;
838  oldestInFlightRobNum = inFlightNodes.begin()->second;
839 
840  // Occupy Load/Store Buffer entry for the issued node if applicable
841  if (new_node->isLoad()) {
842  ++numInFlightLoads;
843  } else if (new_node->isStore()) {
844  ++numInFlightStores;
845  } // else if it is a non load/store node, no buffer entry is occupied
846 
847  printOccupancy();
848 }
849 
850 void
852 {
853  assert(!inFlightNodes.empty());
854  DPRINTFR(TraceCPUData,
855  "\tClearing done seq. num %d from inFlightNodes..\n",
856  done_node->seqNum);
857 
858  assert(inFlightNodes.find(done_node->seqNum) != inFlightNodes.end());
859  inFlightNodes.erase(done_node->seqNum);
860 
861  if (inFlightNodes.empty()) {
862  // If we delete the only in-flight node and then the
863  // oldestInFlightRobNum is set to it's initialized (max) value.
864  oldestInFlightRobNum = UINT64_MAX;
865  } else {
866  // Set the oldest in-flight node rob number equal to the first node in
867  // the inFlightNodes since that will have the numerically least value.
868  oldestInFlightRobNum = inFlightNodes.begin()->second;
869  }
870 
871  DPRINTFR(TraceCPUData,
872  "\tCleared. inFlightNodes.size() = %d, "
873  "oldestInFlightRobNum = %d\n", inFlightNodes.size(),
874  oldestInFlightRobNum);
875 
876  // A store is considered complete when a request is sent, thus ROB entry is
877  // freed. But it occupies an entry in the Store Buffer until its response
878  // is received. A load is considered complete when a response is received,
879  // thus both ROB and Load Buffer entries can be released.
880  if (done_node->isLoad()) {
881  assert(numInFlightLoads != 0);
882  --numInFlightLoads;
883  }
884  // For normal writes, we send the requests out and clear a store buffer
885  // entry on response. For writes which are strictly ordered, for e.g.
886  // writes to device registers, we do that within release() which is called
887  // when node is executed and taken off from readyList.
888  if (done_node->isStore() && done_node->isStrictlyOrdered()) {
889  releaseStoreBuffer();
890  }
891 }
892 
893 void
895 {
896  assert(numInFlightStores != 0);
897  --numInFlightStores;
898 }
899 
900 bool
902  const GraphNode* new_node) const
903 {
904  uint16_t num_in_flight_nodes;
905  if (inFlightNodes.empty()) {
906  num_in_flight_nodes = 0;
907  DPRINTFR(TraceCPUData, "\t\tChecking resources to issue seq. num %lli:"
908  " #in-flight nodes = 0", new_node->seqNum);
909  } else if (new_node->robNum > oldestInFlightRobNum) {
910  // This is the intuitive case where new dep-free node is younger
911  // instruction than the oldest instruction in-flight. Thus we make sure
912  // in_flight_nodes does not overflow.
913  num_in_flight_nodes = new_node->robNum - oldestInFlightRobNum;
914  DPRINTFR(TraceCPUData, "\t\tChecking resources to issue seq. num %lli:"
915  " #in-flight nodes = %d - %d = %d", new_node->seqNum,
916  new_node->robNum, oldestInFlightRobNum, num_in_flight_nodes);
917  } else {
918  // This is the case where an instruction older than the oldest in-
919  // flight instruction becomes dep-free. Thus we must have already
920  // accounted for the entry in ROB for this new dep-free node.
921  // Immediately after this check returns true, oldestInFlightRobNum will
922  // be updated in occupy(). We simply let this node issue now.
923  num_in_flight_nodes = 0;
924  DPRINTFR(TraceCPUData, "\t\tChecking resources to issue seq. num %lli:"
925  " new oldestInFlightRobNum = %d, #in-flight nodes ignored",
926  new_node->seqNum, new_node->robNum);
927  }
928  DPRINTFR(TraceCPUData, ", LQ = %d/%d, SQ = %d/%d.\n",
929  numInFlightLoads, sizeLoadBuffer,
930  numInFlightStores, sizeStoreBuffer);
931  // Check if resources are available to issue the specific node
932  if (num_in_flight_nodes >= sizeROB) {
933  return false;
934  }
935  if (new_node->isLoad() && numInFlightLoads >= sizeLoadBuffer) {
936  return false;
937  }
938  if (new_node->isStore() && numInFlightStores >= sizeStoreBuffer) {
939  return false;
940  }
941  return true;
942 }
943 
944 bool
946 {
947  // Return true if there is at least one read or write request in flight
948  return (numInFlightStores != 0 || numInFlightLoads != 0);
949 }
950 
951 void
953 {
954  DPRINTFR(TraceCPUData, "oldestInFlightRobNum = %d, "
955  "LQ = %d/%d, SQ = %d/%d.\n",
956  oldestInFlightRobNum,
957  numInFlightLoads, sizeLoadBuffer,
958  numInFlightStores, sizeStoreBuffer);
959 }
960 
962  Stats::Group *parent, const std::string& _name) :
963  Stats::Group(parent, _name.c_str()),
964  ADD_STAT(numSendAttempted, UNIT_COUNT,
965  "Number of first attempts to send a request"),
966  ADD_STAT(numSendSucceeded, UNIT_COUNT,
967  "Number of successful first attempts"),
968  ADD_STAT(numSendFailed, UNIT_COUNT, "Number of failed first attempts"),
969  ADD_STAT(numRetrySucceeded, UNIT_COUNT, "Number of successful retries"),
970  ADD_STAT(instLastTick, UNIT_TICK,
971  "Last tick simulated from the fixed inst trace")
972 {
973 
974 }
975 
976 Tick
978 {
979  DPRINTF(TraceCPUInst, "Initializing instruction fetch request generator"
980  " IcacheGen: fixed issue with retry.\n");
981 
982  if (nextExecute()) {
983  DPRINTF(TraceCPUInst, "\tFirst tick = %d.\n", currElement.tick);
984  return currElement.tick;
985  } else {
986  panic("Read of first message in the trace failed.\n");
987  return MaxTick;
988  }
989 }
990 
991 bool
993 {
994  // If there is a retry packet, try to send it
995  if (retryPkt) {
996  DPRINTF(TraceCPUInst, "Trying to send retry packet.\n");
997 
998  if (!port.sendTimingReq(retryPkt)) {
999  // Still blocked! This should never occur.
1000  DPRINTF(TraceCPUInst, "Retry packet sending failed.\n");
1001  return false;
1002  }
1004  } else {
1005  DPRINTF(TraceCPUInst, "Trying to send packet for currElement.\n");
1006 
1007  // try sending current element
1008  assert(currElement.isValid());
1009 
1011 
1014  DPRINTF(TraceCPUInst, "currElement sending failed.\n");
1016  // return false to indicate not to schedule next event
1017  return false;
1018  } else {
1020  }
1021  }
1022  // If packet was sent successfully, either retryPkt or currElement, return
1023  // true to indicate to schedule event at current Tick plus delta. If packet
1024  // was sent successfully and there is no next packet to send, return false.
1025  DPRINTF(TraceCPUInst, "Packet sent successfully, trying to read next "
1026  "element.\n");
1027  retryPkt = nullptr;
1028  // Read next element into currElement, currElement gets cleared so save the
1029  // tick to calculate delta
1030  Tick last_tick = currElement.tick;
1031  if (nextExecute()) {
1032  assert(currElement.tick >= last_tick);
1033  delta = currElement.tick - last_tick;
1034  }
1035  return !traceComplete;
1036 }
1037 
1038 void
1040 {
1041  trace.reset();
1042 }
1043 
1044 bool
1046 {
1047  if (traceComplete)
1048  // We are at the end of the file, thus we have no more messages.
1049  // Return false.
1050  return false;
1051 
1052 
1053  //Reset the currElement to the default values
1054  currElement.clear();
1055 
1056  // Read the next line to get the next message. If that fails then end of
1057  // trace has been reached and traceComplete needs to be set in addition
1058  // to returning false. If successful then next message is in currElement.
1059  if (!trace.read(&currElement)) {
1060  traceComplete = true;
1062  return false;
1063  }
1064 
1065  DPRINTF(TraceCPUInst, "inst fetch: %c addr %d pc %#x size %d tick %d\n",
1066  currElement.cmd.isRead() ? 'r' : 'w',
1067  currElement.addr,
1068  currElement.pc,
1070  currElement.tick);
1071 
1072  return true;
1073 }
1074 
1075 bool
1076 TraceCPU::FixedRetryGen::send(Addr addr, unsigned size, const MemCmd& cmd,
1077  Request::FlagsType flags, Addr pc)
1078 {
1079 
1080  // Create new request
1081  auto req = std::make_shared<Request>(addr, size, flags, requestorId);
1082  req->setPC(pc);
1083 
1084  // If this is not done it triggers assert in L1 cache for invalid contextId
1085  req->setContext(ContextID(0));
1086 
1087  // Embed it in a packet
1088  PacketPtr pkt = new Packet(req, cmd);
1089 
1090  uint8_t* pkt_data = new uint8_t[req->getSize()];
1091  pkt->dataDynamic(pkt_data);
1092 
1093  if (cmd.isWrite()) {
1094  memset(pkt_data, 0xA, req->getSize());
1095  }
1096 
1097  // Call RequestPort method to send a timing request for this packet
1098  bool success = port.sendTimingReq(pkt);
1099  if (!success) {
1100  // If it fails, save the packet to retry when a retry is signalled by
1101  // the cache
1102  retryPkt = pkt;
1103  }
1104  return success;
1105 }
1106 
1107 void
1109 {
1110  // Schedule an event to go through the control flow in the same tick as
1111  // retry is received
1112  DPRINTF(TraceCPUInst, "Icache retry received. Scheduling next IcacheGen"
1113  " event @%lli.\n", curTick());
1115 }
1116 
1117 void
1119 {
1120  // Schedule an event to go through the execute flow in the same tick as
1121  // retry is received
1122  DPRINTF(TraceCPUData, "Dcache retry received. Scheduling next DcacheGen"
1123  " event @%lli.\n", curTick());
1125 }
1126 
1127 void
1129 {
1130  if (!dcacheNextEvent.scheduled()) {
1131  DPRINTF(TraceCPUData, "Scheduling next DcacheGen event at %lli.\n",
1132  when);
1133  schedule(dcacheNextEvent, when);
1135  } else if (when < dcacheNextEvent.when()) {
1136  DPRINTF(TraceCPUData, "Re-scheduling next dcache event from %lli"
1137  " to %lli.\n", dcacheNextEvent.when(), when);
1138  reschedule(dcacheNextEvent, when);
1139  }
1140 
1141 }
1142 
1143 bool
1145 {
1146  // All responses on the instruction fetch side are ignored. Simply delete
1147  // the packet to free allocated memory
1148  delete pkt;
1149 
1150  return true;
1151 }
1152 
1153 void
1155 {
1157 }
1158 
1159 void
1161 {
1162  DPRINTF(TraceCPUData, "Received timing response from Dcache.\n");
1164 }
1165 
1166 bool
1168 {
1169  // Handle the responses for data memory requests which is done inside the
1170  // elastic data generator
1172  // After processing the response delete the packet to free
1173  // memory
1174  delete pkt;
1175 
1176  return true;
1177 }
1178 
1179 void
1181 {
1183 }
1184 
1186  const std::string& filename, const double time_multiplier) :
1187  trace(filename),
1188  timeMultiplier(time_multiplier),
1189  microOpCount(0)
1190 {
1191  // Create a protobuf message for the header and read it from the stream
1192  ProtoMessage::InstDepRecordHeader header_msg;
1193  if (!trace.read(header_msg)) {
1194  panic("Failed to read packet header from %s\n", filename);
1195 
1196  if (header_msg.tick_freq() != SimClock::Frequency) {
1197  panic("Trace %s was recorded with a different tick frequency %d\n",
1198  header_msg.tick_freq());
1199  }
1200  } else {
1201  // Assign window size equal to the field in the trace that was recorded
1202  // when the data dependency trace was captured in the o3cpu model
1203  windowSize = header_msg.window_size();
1204  }
1205 }
1206 
1207 void
1209 {
1210  trace.reset();
1211 }
1212 
1213 bool
1215 {
1216  ProtoMessage::InstDepRecord pkt_msg;
1217  if (trace.read(pkt_msg)) {
1218  // Required fields
1219  element->seqNum = pkt_msg.seq_num();
1220  element->type = pkt_msg.type();
1221  // Scale the compute delay to effectively scale the Trace CPU frequency
1222  element->compDelay = pkt_msg.comp_delay() * timeMultiplier;
1223 
1224  // Repeated field robDepList
1225  element->robDep.clear();
1226  for (int i = 0; i < (pkt_msg.rob_dep()).size(); i++) {
1227  element->robDep.push_back(pkt_msg.rob_dep(i));
1228  }
1229 
1230  // Repeated field
1231  element->regDep.clear();
1232  for (int i = 0; i < (pkt_msg.reg_dep()).size(); i++) {
1233  // There is a possibility that an instruction has both, a register
1234  // and order dependency on an instruction. In such a case, the
1235  // register dependency is omitted
1236  bool duplicate = false;
1237  for (auto &dep: element->robDep) {
1238  duplicate |= (pkt_msg.reg_dep(i) == dep);
1239  }
1240  if (!duplicate)
1241  element->regDep.push_back(pkt_msg.reg_dep(i));
1242  }
1243 
1244  // Optional fields
1245  if (pkt_msg.has_p_addr())
1246  element->physAddr = pkt_msg.p_addr();
1247  else
1248  element->physAddr = 0;
1249 
1250  if (pkt_msg.has_v_addr())
1251  element->virtAddr = pkt_msg.v_addr();
1252  else
1253  element->virtAddr = 0;
1254 
1255  if (pkt_msg.has_size())
1256  element->size = pkt_msg.size();
1257  else
1258  element->size = 0;
1259 
1260  if (pkt_msg.has_flags())
1261  element->flags = pkt_msg.flags();
1262  else
1263  element->flags = 0;
1264 
1265  if (pkt_msg.has_pc())
1266  element->pc = pkt_msg.pc();
1267  else
1268  element->pc = 0;
1269 
1270  // ROB occupancy number
1271  ++microOpCount;
1272  if (pkt_msg.has_weight()) {
1273  microOpCount += pkt_msg.weight();
1274  }
1275  element->robNum = microOpCount;
1276  return true;
1277  }
1278 
1279  // We have reached the end of the file
1280  return false;
1281 }
1282 
1283 bool
1285 {
1286  for (auto it = regDep.begin(); it != regDep.end(); it++) {
1287  if (*it == reg_dep) {
1288  // If register dependency is found, erase it.
1289  regDep.erase(it);
1290  DPRINTFR(TraceCPUData,
1291  "\tFor %lli: Marking register dependency %lli done.\n",
1292  seqNum, reg_dep);
1293  return true;
1294  }
1295  }
1296 
1297  // Return false if the dependency is not found
1298  return false;
1299 }
1300 
1301 bool
1303 {
1304  for (auto it = robDep.begin(); it != robDep.end(); it++) {
1305  if (*it == rob_dep) {
1306  // If the rob dependency is found, erase it.
1307  robDep.erase(it);
1308  DPRINTFR(TraceCPUData,
1309  "\tFor %lli: Marking ROB dependency %lli done.\n",
1310  seqNum, rob_dep);
1311  return true;
1312  }
1313  }
1314  return false;
1315 }
1316 
1317 bool
1319 {
1320  // If it is an rob dependency then remove it
1321  if (!removeRobDep(done_seq_num)) {
1322  // If it is not an rob dependency then it must be a register dependency
1323  // If the register dependency is not found, it violates an assumption
1324  // and must be caught by assert.
1325  M5_VAR_USED bool regdep_found = removeRegDep(done_seq_num);
1326  assert(regdep_found);
1327  }
1328  // Return true if the node is dependency free
1329  return robDep.empty() && regDep.empty();
1330 }
1331 
1332 void
1334 {
1335 #if TRACING_ON
1336  DPRINTFR(TraceCPUData, "%lli", seqNum);
1337  DPRINTFR(TraceCPUData, ",%s", typeToStr());
1338  if (isLoad() || isStore()) {
1339  DPRINTFR(TraceCPUData, ",%i", physAddr);
1340  DPRINTFR(TraceCPUData, ",%i", size);
1341  DPRINTFR(TraceCPUData, ",%i", flags);
1342  }
1343  DPRINTFR(TraceCPUData, ",%lli", compDelay);
1344  DPRINTFR(TraceCPUData, "robDep:");
1345  for (auto &dep: robDep) {
1346  DPRINTFR(TraceCPUData, ",%lli", dep);
1347  }
1348  DPRINTFR(TraceCPUData, "regDep:");
1349  for (auto &dep: regDep) {
1350  DPRINTFR(TraceCPUData, ",%lli", dep);
1351  }
1352  auto child_itr = dependents.begin();
1353  DPRINTFR(TraceCPUData, "dependents:");
1354  while (child_itr != dependents.end()) {
1355  DPRINTFR(TraceCPUData, ":%lli", (*child_itr)->seqNum);
1356  child_itr++;
1357  }
1358 
1359  DPRINTFR(TraceCPUData, "\n");
1360 #endif // TRACING_ON
1361 }
1362 
1363 std::string
1365 {
1366  return Record::RecordType_Name(type);
1367 }
1368 
1370  : trace(filename)
1371 {
1372  // Create a protobuf message for the header and read it from the stream
1373  ProtoMessage::PacketHeader header_msg;
1374  if (!trace.read(header_msg)) {
1375  panic("Failed to read packet header from %s\n", filename);
1376 
1377  if (header_msg.tick_freq() != SimClock::Frequency) {
1378  panic("Trace %s was recorded with a different tick frequency %d\n",
1379  header_msg.tick_freq());
1380  }
1381  }
1382 }
1383 
1384 void
1386 {
1387  trace.reset();
1388 }
1389 
1390 bool
1392 {
1393  ProtoMessage::Packet pkt_msg;
1394  if (trace.read(pkt_msg)) {
1395  element->cmd = pkt_msg.cmd();
1396  element->addr = pkt_msg.addr();
1397  element->blocksize = pkt_msg.size();
1398  element->tick = pkt_msg.tick();
1399  element->flags = pkt_msg.has_flags() ? pkt_msg.flags() : 0;
1400  element->pc = pkt_msg.has_pc() ? pkt_msg.pc() : 0;
1401  return true;
1402  }
1403 
1404  // We have reached the end of the file
1405  return false;
1406 }
TraceCPU::ElasticDataGen::completeMemAccess
void completeMemAccess(PacketPtr pkt)
When a load writeback is received, that is when the load completes, release the dependents on it.
Definition: trace_cpu.cc:677
TraceCPU::progressMsgInterval
const uint64_t progressMsgInterval
Interval of committed instructions specified by the user at which a progress info message is printed.
Definition: trace_cpu.hh:1097
TraceCPU::schedIcacheNext
void schedIcacheNext()
This is the control flow that uses the functionality of the icacheGen to replay the trace.
Definition: trace_cpu.cc:144
TraceCPU::ElasticDataGen::execute
void execute()
This is the main execute function which consumes nodes from the sorted readyList.
Definition: trace_cpu.cc:365
Event::scheduled
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:462
TraceCPU::ElasticDataGen::GraphNode::removeRobDep
bool removeRobDep(NodeSeqNum rob_dep)
Remove completed instruction from order dependency array.
Definition: trace_cpu.cc:1302
TraceCPU::ElasticDataGen::GraphNode::removeDepOnInst
bool removeDepOnInst(NodeSeqNum done_seq_num)
Check for all dependencies on completed inst.
Definition: trace_cpu.cc:1318
TraceCPU::TraceStats::TraceStats
TraceStats(TraceCPU *trace)
Definition: trace_cpu.cc:203
TraceCPU::takeOverFrom
void takeOverFrom(BaseCPU *oldCPU)
Load the state of a CPU from the previous CPU object, invoked on all new CPUs that are about to be sw...
Definition: trace_cpu.cc:93
TraceCPU::TraceCPU
TraceCPU(const TraceCPUParams &params)
Definition: trace_cpu.cc:45
TraceCPU::traceStats
TraceCPU::TraceStats traceStats
TraceCPU::ElasticDataGen::ElasticDataGenStatGroup::numSendSucceeded
Stats::Scalar numSendSucceeded
Definition: trace_cpu.hh:1017
TraceCPU::TraceStats::numSchedDcacheEvent
Stats::Scalar numSchedDcacheEvent
Definition: trace_cpu.hh:1108
TraceCPU::TraceStats::numSchedIcacheEvent
Stats::Scalar numSchedIcacheEvent
Definition: trace_cpu.hh:1109
TraceCPU::ElasticDataGen::GraphNode::robDep
RobDepList robDep
List of order dependencies.
Definition: trace_cpu.hh:592
BaseCPU::init
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: base.cc:269
TraceCPU::ElasticDataGen::GraphNode::typeToStr
std::string typeToStr() const
Return string specifying the type of the node.
Definition: trace_cpu.cc:1364
Request::FlagsType
uint64_t FlagsType
Definition: request.hh:94
TraceCPU::ElasticDataGen::InputStream::reset
void reset()
Reset the stream such that it can be played once again.
Definition: trace_cpu.cc:1208
ArmISA::i
Bitfield< 7 > i
Definition: miscregs_types.hh:63
BaseCPU::getDataPort
virtual Port & getDataPort()=0
Purely virtual method that returns a reference to the data port.
TraceCPU::FixedRetryGen::init
Tick init()
Called from TraceCPU init().
Definition: trace_cpu.cc:977
EventManager::reschedule
void reschedule(Event &event, Tick when, bool always=false)
Definition: eventq.hh:1034
TraceCPU::ElasticDataGen::InputStream::trace
ProtoInputStream trace
Input file stream for the protobuf trace.
Definition: trace_cpu.hh:763
TraceCPU::ElasticDataGen::addToSortedReadyList
void addToSortedReadyList(NodeSeqNum seq_num, Tick exec_tick)
Add a ready node to the readyList.
Definition: trace_cpu.cc:744
TraceCPU::ElasticDataGen::addDepsOnParent
void addDepsOnParent(GraphNode *new_node, T &dep_list)
Iterate over the dependencies of a new node and add the new node to the list of dependents of the par...
Definition: trace_cpu.cc:340
ContextID
int ContextID
Globally unique thread context ID.
Definition: types.hh:237
TraceCPU::FixedRetryGen::TraceElement::flags
Request::FlagsType flags
Potential request flags to use.
Definition: trace_cpu.hh:349
ProtoInputStream::read
bool read(google::protobuf::Message &msg)
Read a message from the stream.
Definition: protoio.cc:180
TraceCPU::execCompleteEvent
CountedExitEvent * execCompleteEvent
A CountedExitEvent which when serviced decrements the counter.
Definition: trace_cpu.hh:1085
TraceCPU::ElasticDataGen::HardwareResource::HardwareResource
HardwareResource(uint16_t max_rob, uint16_t max_stores, uint16_t max_loads)
Constructor that initializes the sizes of the structures.
Definition: trace_cpu.cc:821
BaseCPU::cacheLineSize
unsigned int cacheLineSize() const
Get the cache line size of the system.
Definition: base.hh:391
UNIT_TICK
#define UNIT_TICK
Definition: units.hh:40
Tick
uint64_t Tick
Tick count type.
Definition: types.hh:59
TraceCPU::oneTraceComplete
bool oneTraceComplete
Set to true when one of the generators finishes replaying its trace.
Definition: trace_cpu.hh:1062
TraceCPU::FixedRetryGen::tickDelta
int64_t tickDelta()
Definition: trace_cpu.hh:474
TraceCPU::FixedRetryGen::owner
TraceCPU & owner
Reference of the TraceCPU.
Definition: trace_cpu.hh:478
TraceCPU::getInstPort
Port & getInstPort()
Used to get a reference to the icache port.
Definition: trace_cpu.hh:1121
Stats::Group::Group
Group()=delete
TraceCPU::ElasticDataGen::GraphNode::physAddr
Addr physAddr
The address for the request if any.
Definition: trace_cpu.hh:577
TraceCPU::schedDcacheNext
void schedDcacheNext()
This is the control flow that uses the functionality of the dcacheGen to replay the trace.
Definition: trace_cpu.cc:170
TraceCPU::ElasticDataGen::requestorId
const RequestorID requestorId
RequestorID used for the requests being sent.
Definition: trace_cpu.hh:954
Packet::req
RequestPtr req
A pointer to the original request.
Definition: packet.hh:341
TraceCPU::checkAndSchedExitEvent
void checkAndSchedExitEvent()
This is called when either generator finishes executing from the trace.
Definition: trace_cpu.cc:184
DTRACE
#define DTRACE(x)
Definition: debug.hh:156
TraceCPU::ElasticDataGen::HardwareResource::awaitingResponse
bool awaitingResponse() const
Check if there are any outstanding requests, i.e.
Definition: trace_cpu.cc:945
BaseCPU::baseStats
BaseCPU::BaseCPUStats baseStats
Packet::dataDynamic
void dataDynamic(T *p)
Set the data pointer to a value that should have delete [] called on it.
Definition: packet.hh:1146
TraceCPU::ElasticDataGen::trace
InputStream trace
Input stream used for reading the input trace file.
Definition: trace_cpu.hh:957
TraceCPU::ElasticDataGen::GraphNode::robNum
NodeRobNum robNum
ROB occupancy number.
Definition: trace_cpu.hh:568
TraceCPU::init
void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: trace_cpu.cc:101
TraceCPU::ElasticDataGen::readyList
std::list< ReadyNode > readyList
List of nodes that are ready to execute.
Definition: trace_cpu.hh:1004
TraceCPU::ElasticDataGen::ReadyNode
Struct to store a ready-to-execute node and its execution tick.
Definition: trace_cpu.hh:645
TraceCPU::ElasticDataGen::ElasticDataGenStatGroup::numSendFailed
Stats::Scalar numSendFailed
Definition: trace_cpu.hh:1018
Event::when
Tick when() const
Get the time that the event is scheduled.
Definition: eventq.hh:505
sim_exit.hh
TraceCPU::ElasticDataGen::hwResource
HardwareResource hwResource
Hardware resources required to contain in-flight nodes and to throttle issuing of new nodes when reso...
Definition: trace_cpu.hh:989
X86ISA::physAddr
physAddr
Definition: misc.hh:831
Port::takeOverFrom
void takeOverFrom(Port *old)
A utility function to make it easier to swap out ports.
Definition: port.hh:132
TraceCPU::FixedRetryGen::FixedRetryGenStatGroup::instLastTick
Stats::Scalar instLastTick
Last simulated tick by the FixedRetryGen.
Definition: trace_cpu.hh:521
TraceCPU::icacheGen
FixedRetryGen icacheGen
Instance of FixedRetryGen to replay instruction read requests.
Definition: trace_cpu.hh:1029
TraceCPU::FixedRetryGen::TraceElement
This struct stores a line in the trace file.
Definition: trace_cpu.hh:333
SimClock::Frequency
Tick Frequency
The simulated frequency of curTick(). (In ticks per second)
Definition: core.cc:43
TraceCPU::ElasticDataGen::adjustInitTraceOffset
void adjustInitTraceOffset(Tick &offset)
Adjust traceOffset based on what TraceCPU init() determines on comparing the offsets in the fetch req...
Definition: trace_cpu.cc:273
TraceCPU::FixedRetryGen::traceComplete
bool traceComplete
Set to true when end of trace is reached.
Definition: trace_cpu.hh:505
TraceCPU::ElasticDataGen::GraphNode::seqNum
NodeSeqNum seqNum
Instruction sequence number.
Definition: trace_cpu.hh:565
TraceCPU::FixedRetryGen::InputStream::read
bool read(TraceElement *element)
Attempt to read a trace element from the stream, and also notify the caller if the end of the file wa...
Definition: trace_cpu.cc:1391
TraceCPU::FixedRetryGen::port
RequestPort & port
Reference of the port to be used to issue memory requests.
Definition: trace_cpu.hh:481
TraceCPU::ElasticDataGen::GraphNode::isStrictlyOrdered
bool isStrictlyOrdered() const
Return true if node has a request which is strictly ordered.
Definition: trace_cpu.hh:630
TraceCPU::FixedRetryGen::FixedRetryGenStatGroup::numSendAttempted
Stats::Scalar numSendAttempted
Stats for instruction accesses replayed.
Definition: trace_cpu.hh:516
TraceCPU::FixedRetryGen::exit
void exit()
Exit the FixedRetryGen.
Definition: trace_cpu.cc:1039
TraceCPU::FixedRetryGen::isTraceComplete
bool isTraceComplete()
Returns the traceComplete variable which is set when end of the input trace file is reached.
Definition: trace_cpu.hh:472
X86ISA::system
Bitfield< 15 > system
Definition: misc.hh:997
TraceCPU::FixedRetryGen::FixedRetryGenStatGroup::FixedRetryGenStatGroup
FixedRetryGenStatGroup(Stats::Group *parent, const std::string &_name)
name is the extension to the name for these stats
Definition: trace_cpu.cc:961
TraceCPU::dcacheRetryRecvd
void dcacheRetryRecvd()
When data cache port receives a retry, schedule event dcacheNextEvent.
Definition: trace_cpu.cc:1118
TraceCPU::ElasticDataGen::port
RequestPort & port
Reference of the port to be used to issue memory requests.
Definition: trace_cpu.hh:951
EventManager::schedule
void schedule(Event &event, Tick when)
Definition: eventq.hh:1016
MemCmd::isRead
bool isRead() const
Definition: packet.hh:200
TraceCPU::FixedRetryGen::FixedRetryGenStatGroup::numSendSucceeded
Stats::Scalar numSendSucceeded
Definition: trace_cpu.hh:517
TraceCPU::FixedRetryGen::nextExecute
bool nextExecute()
Reads a line of the trace file.
Definition: trace_cpu.cc:1045
Stats::ScalarBase::value
Counter value() const
Return the current value of this stat as its base type.
Definition: statistics.hh:603
TraceCPU::ElasticDataGen::owner
TraceCPU & owner
Reference of the TraceCPU.
Definition: trace_cpu.hh:948
TraceCPU::FixedRetryGen::InputStream::InputStream
InputStream(const std::string &filename)
Create a trace input stream for a given file name.
Definition: trace_cpu.cc:1369
TraceCPU::FixedRetryGen::TraceElement::cmd
MemCmd cmd
Specifies if the request is to be a read or a write.
Definition: trace_cpu.hh:337
RequestPort::sendTimingReq
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
Definition: port.hh:492
TraceCPU::FixedRetryGen::FixedRetryGenStatGroup::numRetrySucceeded
Stats::Scalar numRetrySucceeded
Definition: trace_cpu.hh:519
TraceCPU::DcachePort::recvReqRetry
void recvReqRetry()
Handle a retry signalled by the cache if data access failed in the first attempt.
Definition: trace_cpu.cc:1180
TraceCPU::DcachePort::recvTimingResp
bool recvTimingResp(PacketPtr pkt)
Receive the timing reponse and call dcacheRecvTimingResp() method of the dcacheGen to handle completi...
Definition: trace_cpu.cc:1167
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:237
ADD_STAT
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition: group.hh:71
TraceCPU::ElasticDataGen::elasticStats
TraceCPU::ElasticDataGen::ElasticDataGenStatGroup elasticStats
MemCmd
Definition: packet.hh:72
TraceCPU::FixedRetryGen::currElement
TraceElement currElement
Store an element read from the trace to send as the next packet.
Definition: trace_cpu.hh:508
TraceCPU::FixedRetryGen::TraceElement::pc
Addr pc
Instruction PC.
Definition: trace_cpu.hh:352
MipsISA::pc
Bitfield< 4 > pc
Definition: pra_constants.hh:240
TraceCPU::IcachePort::recvTimingResp
bool recvTimingResp(PacketPtr pkt)
Receive the timing reponse and simply delete the packet since instruction fetch requests are issued a...
Definition: trace_cpu.cc:1144
Packet::createRead
static PacketPtr createRead(const RequestPtr &req)
Constructor-like methods that return Packets based on Request objects.
Definition: packet.hh:981
TraceCPU::ElasticDataGen::GraphNode::flags
Request::Flags flags
Request flags if any.
Definition: trace_cpu.hh:586
TraceCPU::ElasticDataGen::execComplete
bool execComplete
Set true when execution of trace is complete.
Definition: trace_cpu.hh:972
TraceCPU::FixedRetryGen::TraceElement::tick
Tick tick
The time at which the request should be sent.
Definition: trace_cpu.hh:346
TraceCPU::ElasticDataGen::GraphNode::removeRegDep
bool removeRegDep(NodeSeqNum reg_dep)
Remove completed instruction from register dependency array.
Definition: trace_cpu.cc:1284
TraceCPU::ElasticDataGen::ElasticDataGenStatGroup::numSOStores
Stats::Scalar numSOStores
Definition: trace_cpu.hh:1022
TraceCPU::ElasticDataGen::printReadyList
void printReadyList()
Print readyList for debugging using debug flag TraceCPUData.
Definition: trace_cpu.cc:804
TraceCPU::ElasticDataGen::GraphNode::dependents
std::vector< GraphNode * > dependents
A vector of nodes dependent (outgoing) on this node.
Definition: trace_cpu.hh:608
Clocked::clockEdge
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...
Definition: clocked_object.hh:174
TraceCPU::ElasticDataGen::GraphNode::compDelay
uint64_t compDelay
Computational delay.
Definition: trace_cpu.hh:595
TraceCPU::ElasticDataGen::HardwareResource::isAvailable
bool isAvailable(const GraphNode *new_node) const
Check if structures required to issue a node are free.
Definition: trace_cpu.cc:901
TraceCPU::ElasticDataGen::GraphNode
The struct GraphNode stores an instruction in the trace file.
Definition: trace_cpu.hh:555
DPRINTFR
#define DPRINTFR(...)
Definition: trace.hh:239
exitSimLoop
void exitSimLoop(const std::string &message, int exit_code, Tick when, Tick repeat, bool serialize)
Schedule an event to exit the simulation loop (returning to Python) at the end of the current cycle (...
Definition: sim_events.cc:85
TraceCPU::ElasticDataGen::init
Tick init()
Called from TraceCPU init().
Definition: trace_cpu.cc:242
TraceCPU::progressMsgThreshold
uint64_t progressMsgThreshold
Definition: trace_cpu.hh:1104
TraceCPU::ElasticDataGen::GraphNode::pc
Addr pc
Instruction PC.
Definition: trace_cpu.hh:589
TraceCPU::ElasticDataGen::GraphNode::isStore
bool isStore() const
Is the node a store.
Definition: trace_cpu.hh:614
TraceCPU::ElasticDataGen::ElasticDataGenStatGroup::numSplitReqs
Stats::Scalar numSplitReqs
Definition: trace_cpu.hh:1020
TraceCPU::ElasticDataGen::readNextWindow
bool readNextWindow()
Reads a line of the trace file.
Definition: trace_cpu.cc:287
TraceCPU::enableEarlyExit
const bool enableEarlyExit
Exit when any one Trace CPU completes its execution.
Definition: trace_cpu.hh:1091
BaseCPU::BaseCPUStats::numCycles
Stats::Scalar numCycles
Definition: base.hh:606
UNIT_COUNT
#define UNIT_COUNT
Definition: units.hh:49
TraceCPU::ElasticDataGen::depGraph
std::unordered_map< NodeSeqNum, GraphNode * > depGraph
Store the depGraph of GraphNodes.
Definition: trace_cpu.hh:992
TraceCPU::icacheNextEvent
EventFunctionWrapper icacheNextEvent
Event for the control flow method schedIcacheNext()
Definition: trace_cpu.hh:1050
TraceCPU::schedDcacheNextEvent
void schedDcacheNextEvent(Tick when)
Schedule event dcacheNextEvent at the given tick.
Definition: trace_cpu.cc:1128
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:148
TraceCPU::ElasticDataGen::InputStream::InputStream
InputStream(const std::string &filename, const double time_multiplier)
Create a trace input stream for a given file name.
Definition: trace_cpu.cc:1185
TraceCPU::ElasticDataGen::HardwareResource::releaseStoreBuffer
void releaseStoreBuffer()
Release store buffer entry for a completed store.
Definition: trace_cpu.cc:894
name
const std::string & name()
Definition: trace.cc:48
TraceCPU::FixedRetryGen::TraceElement::clear
void clear()
Make this element invalid.
Definition: trace_cpu.hh:364
Clocked::clockPeriod
Tick clockPeriod() const
Definition: clocked_object.hh:214
TraceCPU::ElasticDataGen::GraphNode::type
RecordType type
Type of the node corresponding to the instruction modeled by it.
Definition: trace_cpu.hh:574
TraceCPU::FixedRetryGen::trace
InputStream trace
Input stream used for reading the input trace file.
Definition: trace_cpu.hh:487
MemCmd::cmd
Command cmd
Definition: packet.hh:190
X86ISA::addr
Bitfield< 3 > addr
Definition: types.hh:80
SimObject::name
virtual const std::string name() const
Definition: sim_object.hh:182
BaseCPU
Definition: base.hh:104
TraceCPU::ElasticDataGen::ElasticDataGenStatGroup::numRetrySucceeded
Stats::Scalar numRetrySucceeded
Definition: trace_cpu.hh:1019
UNIT_RATE
#define UNIT_RATE(T1, T2)
Definition: units.hh:47
Packet::createWrite
static PacketPtr createWrite(const RequestPtr &req)
Definition: packet.hh:987
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
TraceCPU::ElasticDataGen::InputStream::read
bool read(GraphNode *element)
Attempt to read a trace element from the stream, and also notify the caller if the end of the file wa...
Definition: trace_cpu.cc:1214
TraceCPU::ElasticDataGen::ElasticDataGenStatGroup::numSOLoads
Stats::Scalar numSOLoads
Definition: trace_cpu.hh:1021
TraceCPU::FixedRetryGen::send
bool send(Addr addr, unsigned size, const MemCmd &cmd, Request::FlagsType flags, Addr pc)
Creates a new request assigning the request parameters passed by the arguments.
Definition: trace_cpu.cc:1076
inform
#define inform(...)
Definition: logging.hh:240
TraceCPU::ElasticDataGen::GraphNode::size
uint32_t size
Size of request if any.
Definition: trace_cpu.hh:583
TraceCPU::ElasticDataGen::ReadyNode::seqNum
NodeSeqNum seqNum
The sequence number of the ready node.
Definition: trace_cpu.hh:648
TraceCPU::ElasticDataGen::ElasticDataGenStatGroup::dataLastTick
Stats::Scalar dataLastTick
Tick when ElasticDataGen completes execution.
Definition: trace_cpu.hh:1024
TraceCPU::dcacheRecvTimingResp
void dcacheRecvTimingResp(PacketPtr pkt)
When data cache port receives a response, this calls the dcache generator method handle to complete t...
Definition: trace_cpu.cc:1160
TraceCPU::FixedRetryGen::InputStream::reset
void reset()
Reset the stream such that it can be played once again.
Definition: trace_cpu.cc:1385
TraceCPU::ElasticDataGen::ElasticDataGenStatGroup::ElasticDataGenStatGroup
ElasticDataGenStatGroup(Stats::Group *parent, const std::string &_name)
name is the extension to the name for these stats
Definition: trace_cpu.cc:220
Stats::DataWrap::precision
Derived & precision(int _precision)
Set the precision and marks this stat to print at the end of simulation.
Definition: statistics.hh:327
TraceCPU::ElasticDataGen::HardwareResource::release
void release(const GraphNode *done_node)
Release appropriate structures for a completed node.
Definition: trace_cpu.cc:851
TraceCPU::ElasticDataGen::exit
void exit()
Exit the ElasticDataGen.
Definition: trace_cpu.cc:281
TraceCPU::ElasticDataGen::executeMemReq
PacketPtr executeMemReq(GraphNode *node_ptr)
Creates a new request for a load or store assigning the request parameters.
Definition: trace_cpu.cc:561
TraceCPU::FixedRetryGen::fixedStats
TraceCPU::FixedRetryGen::FixedRetryGenStatGroup fixedStats
TraceCPU::ElasticDataGen::GraphNode::regDep
RegDepList regDep
List of register dependencies (incoming) if any.
Definition: trace_cpu.hh:601
TraceCPU::ElasticDataGen::HardwareResource::occupy
void occupy(const GraphNode *new_node)
Occupy appropriate structures for an issued node.
Definition: trace_cpu.cc:832
TraceCPU::ElasticDataGen::ElasticDataGenStatGroup::maxReadyListSize
Stats::Scalar maxReadyListSize
Definition: trace_cpu.hh:1015
Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:258
Stats::Group
Statistics container.
Definition: group.hh:87
TraceCPU::ElasticDataGen::depFreeQueue
std::queue< const GraphNode * > depFreeQueue
Queue of dependency-free nodes that are pending issue because resources are not available.
Definition: trace_cpu.hh:1001
TraceCPU::TraceStats::numOps
Stats::Scalar numOps
Stat for number of simulated micro-ops.
Definition: trace_cpu.hh:1112
TraceCPU::ElasticDataGen::ElasticDataGenStatGroup::numSendAttempted
Stats::Scalar numSendAttempted
Definition: trace_cpu.hh:1016
Cycles
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:79
TraceCPU::FixedRetryGen::TraceElement::isValid
bool isValid() const
Check validity of this element.
Definition: trace_cpu.hh:359
Packet::isWrite
bool isWrite() const
Definition: packet.hh:558
CountedExitEvent
Definition: sim_events.hh:101
TraceCPU::dataTraceFile
std::string dataTraceFile
Definition: trace_cpu.hh:317
TraceCPU::ElasticDataGen::NodeSeqNum
uint64_t NodeSeqNum
Node sequence number type.
Definition: trace_cpu.hh:541
TraceCPU::numTraceCPUs
static int numTraceCPUs
Number of Trace CPUs in the system used as a shared variable and passed to the CountedExitEvent event...
Definition: trace_cpu.hh:1078
TraceCPU::ElasticDataGen::GraphNode::isLoad
bool isLoad() const
Is the node a load.
Definition: trace_cpu.hh:611
TraceCPU::ElasticDataGen::retryPkt
PacketPtr retryPkt
PacketPtr used to store the packet to retry.
Definition: trace_cpu.hh:963
TraceCPU::ElasticDataGen::GraphNode::virtAddr
Addr virtAddr
The virtual address for the request if any.
Definition: trace_cpu.hh:580
X86ISA::type
type
Definition: misc.hh:727
Stats
Definition: statistics.cc:53
TraceCPU::ElasticDataGen::ElasticDataGenStatGroup::maxDependents
Stats::Scalar maxDependents
Stats for data memory accesses replayed.
Definition: trace_cpu.hh:1014
curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:43
TraceCPU::ElasticDataGen::traceComplete
bool traceComplete
Set to true when end of trace is reached.
Definition: trace_cpu.hh:966
TraceCPU::ElasticDataGen::checkAndIssue
bool checkAndIssue(const GraphNode *node_ptr, bool first=true)
Attempts to issue a node once the node's source dependencies are complete.
Definition: trace_cpu.cc:637
TraceCPU::FixedRetryGen::tryNext
bool tryNext()
This tries to send current or retry packet and returns true if successfull.
Definition: trace_cpu.cc:992
TraceCPU::ElasticDataGen::windowSize
const uint32_t windowSize
Window size within which to check for dependencies.
Definition: trace_cpu.hh:983
TraceCPU::dcacheNextEvent
EventFunctionWrapper dcacheNextEvent
Event for the control flow method schedDcacheNext()
Definition: trace_cpu.hh:1053
TraceCPU::FixedRetryGen::TraceElement::addr
Addr addr
The address for the request.
Definition: trace_cpu.hh:340
TraceCPU::FixedRetryGen::InputStream::trace
ProtoInputStream trace
Definition: trace_cpu.hh:376
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:219
TraceCPU::ElasticDataGen::nextRead
bool nextRead
Set to true when the next window of instructions need to be read.
Definition: trace_cpu.hh:969
TraceCPU::FixedRetryGen::FixedRetryGenStatGroup::numSendFailed
Stats::Scalar numSendFailed
Definition: trace_cpu.hh:518
TraceCPU::IcachePort::recvReqRetry
void recvReqRetry()
Handle a retry signalled by the cache if instruction read failed in the first attempt.
Definition: trace_cpu.cc:1154
TraceCPU::FixedRetryGen::requestorId
const RequestorID requestorId
RequestorID used for the requests being sent.
Definition: trace_cpu.hh:484
TraceCPU::getDataPort
Port & getDataPort()
Used to get a reference to the dcache port.
Definition: trace_cpu.hh:1124
TraceCPU::ElasticDataGen::HardwareResource::printOccupancy
void printOccupancy()
Print resource occupancy for debugging.
Definition: trace_cpu.cc:952
TraceCPU::icacheRetryRecvd
void icacheRetryRecvd()
When instruction cache port receives a retry, schedule event icacheNextEvent.
Definition: trace_cpu.cc:1108
TraceCPU::FixedRetryGen::retryPkt
PacketPtr retryPkt
PacketPtr used to store the packet to retry.
Definition: trace_cpu.hh:493
BaseCPU::getInstPort
virtual Port & getInstPort()=0
Purely virtual method that returns a reference to the instruction port.
TraceCPU::updateNumOps
void updateNumOps(uint64_t rob_num)
Definition: trace_cpu.cc:82
MaxTick
const Tick MaxTick
Definition: types.hh:61
TraceCPU::TraceStats::cpi
Stats::Formula cpi
Stat for the CPI.
Definition: trace_cpu.hh:1115
TraceCPU::ElasticDataGen::InputStream::windowSize
uint32_t windowSize
The window size that is read from the header of the protobuf trace and used to process the dependency...
Definition: trace_cpu.hh:780
trace_cpu.hh
TraceCPU::FixedRetryGen::TraceElement::blocksize
Addr blocksize
The size of the access for the request.
Definition: trace_cpu.hh:343
TraceCPU::dcacheGen
ElasticDataGen dcacheGen
Instance of ElasticDataGen to replay data read and write requests.
Definition: trace_cpu.hh:1032
MemCmd::isWrite
bool isWrite() const
Definition: packet.hh:201
TraceCPU::traceOffset
Tick traceOffset
This stores the time offset in the trace, which is taken away from the ready times of requests.
Definition: trace_cpu.hh:1070
TraceCPU::ElasticDataGen::ReadyNode::execTick
Tick execTick
The tick at which the ready node must be executed.
Definition: trace_cpu.hh:651
TraceCPU::FixedRetryGen::delta
int64_t delta
Stores the difference in the send ticks of the current and last packets.
Definition: trace_cpu.hh:500
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:171
TraceCPU::instTraceFile
std::string instTraceFile
File names for input instruction and data traces.
Definition: trace_cpu.hh:317
TraceCPU
The trace cpu replays traces generated using the elastic trace probe attached to the O3 CPU model.
Definition: trace_cpu.hh:140
TraceCPU::ElasticDataGen::GraphNode::writeElementAsTrace
void writeElementAsTrace() const
Write out element in trace-compatible format using debug flag TraceCPUData.
Definition: trace_cpu.cc:1333
ArmISA::offset
Bitfield< 23, 0 > offset
Definition: types.hh:153
TraceCPU::ElasticDataGen::isExecComplete
bool isExecComplete() const
Returns the execComplete variable which is set when the last node is executed.
Definition: trace_cpu.hh:929

Generated on Tue Jun 22 2021 15:28:27 for gem5 by doxygen 1.8.17