gem5  v20.1.0.0
inst_queue_impl.hh
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2014, 2017-2020 ARM Limited
3  * Copyright (c) 2013 Advanced Micro Devices, Inc.
4  * All rights reserved.
5  *
6  * The license below extends only to copyright in the software and shall
7  * not be construed as granting a license to any other intellectual
8  * property including but not limited to intellectual property relating
9  * to a hardware implementation of the functionality of the software
10  * licensed hereunder. You may use the software subject to the license
11  * terms below provided that you ensure that this notice is replicated
12  * unmodified and in its entirety in all distributions of the software,
13  * modified or unmodified, in source code or in binary form.
14  *
15  * Copyright (c) 2004-2006 The Regents of The University of Michigan
16  * All rights reserved.
17  *
18  * Redistribution and use in source and binary forms, with or without
19  * modification, are permitted provided that the following conditions are
20  * met: redistributions of source code must retain the above copyright
21  * notice, this list of conditions and the following disclaimer;
22  * redistributions in binary form must reproduce the above copyright
23  * notice, this list of conditions and the following disclaimer in the
24  * documentation and/or other materials provided with the distribution;
25  * neither the name of the copyright holders nor the names of its
26  * contributors may be used to endorse or promote products derived from
27  * this software without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40  */
41 
42 #ifndef __CPU_O3_INST_QUEUE_IMPL_HH__
43 #define __CPU_O3_INST_QUEUE_IMPL_HH__
44 
45 #include <limits>
46 #include <vector>
47 
48 #include "base/logging.hh"
49 #include "cpu/o3/fu_pool.hh"
50 #include "cpu/o3/inst_queue.hh"
51 #include "debug/IQ.hh"
52 #include "enums/OpClass.hh"
53 #include "params/DerivO3CPU.hh"
54 #include "sim/core.hh"
55 
56 // clang complains about std::set being overloaded with Packet::set if
57 // we open up the entire namespace std
58 using std::list;
59 
60 template <class Impl>
62  int fu_idx, InstructionQueue<Impl> *iq_ptr)
63  : Event(Stat_Event_Pri, AutoDelete),
64  inst(_inst), fuIdx(fu_idx), iqPtr(iq_ptr), freeFU(false)
65 {
66 }
67 
68 template <class Impl>
69 void
71 {
72  iqPtr->processFUCompletion(inst, freeFU ? fuIdx : -1);
73  inst = NULL;
74 }
75 
76 
77 template <class Impl>
78 const char *
80 {
81  return "Functional unit completion";
82 }
83 
84 template <class Impl>
86  DerivO3CPUParams *params)
87  : cpu(cpu_ptr),
88  iewStage(iew_ptr),
89  fuPool(params->fuPool),
90  iqPolicy(params->smtIQPolicy),
91  numEntries(params->numIQEntries),
92  totalWidth(params->issueWidth),
94 {
95  assert(fuPool);
96 
97  numThreads = params->numThreads;
98 
99  // Set the number of total physical registers
100  // As the vector registers have two addressing modes, they are added twice
101  numPhysRegs = params->numPhysIntRegs + params->numPhysFloatRegs +
102  params->numPhysVecRegs +
103  params->numPhysVecRegs * TheISA::NumVecElemPerVecReg +
104  params->numPhysVecPredRegs +
105  params->numPhysCCRegs;
106 
107  //Create an entry for each physical register within the
108  //dependency graph.
109  dependGraph.resize(numPhysRegs);
110 
111  // Resize the register scoreboard.
112  regScoreboard.resize(numPhysRegs);
113 
114  //Initialize Mem Dependence Units
115  for (ThreadID tid = 0; tid < Impl::MaxThreads; tid++) {
116  memDepUnit[tid].init(params, tid);
117  memDepUnit[tid].setIQ(this);
118  }
119 
120  resetState();
121 
122  //Figure out resource sharing policy
123  if (iqPolicy == SMTQueuePolicy::Dynamic) {
124  //Set Max Entries to Total ROB Capacity
125  for (ThreadID tid = 0; tid < numThreads; tid++) {
126  maxEntries[tid] = numEntries;
127  }
128 
129  } else if (iqPolicy == SMTQueuePolicy::Partitioned) {
130  //@todo:make work if part_amt doesnt divide evenly.
131  int part_amt = numEntries / numThreads;
132 
133  //Divide ROB up evenly
134  for (ThreadID tid = 0; tid < numThreads; tid++) {
135  maxEntries[tid] = part_amt;
136  }
137 
138  DPRINTF(IQ, "IQ sharing policy set to Partitioned:"
139  "%i entries per thread.\n",part_amt);
140  } else if (iqPolicy == SMTQueuePolicy::Threshold) {
141  double threshold = (double)params->smtIQThreshold / 100;
142 
143  int thresholdIQ = (int)((double)threshold * numEntries);
144 
145  //Divide up by threshold amount
146  for (ThreadID tid = 0; tid < numThreads; tid++) {
147  maxEntries[tid] = thresholdIQ;
148  }
149 
150  DPRINTF(IQ, "IQ sharing policy set to Threshold:"
151  "%i entries per thread.\n",thresholdIQ);
152  }
153  for (ThreadID tid = numThreads; tid < Impl::MaxThreads; tid++) {
154  maxEntries[tid] = 0;
155  }
156 }
157 
158 template <class Impl>
160 {
161  dependGraph.reset();
162 #ifdef DEBUG
163  cprintf("Nodes traversed: %i, removed: %i\n",
164  dependGraph.nodesTraversed, dependGraph.nodesRemoved);
165 #endif
166 }
167 
168 template <class Impl>
169 std::string
171 {
172  return cpu->name() + ".iq";
173 }
174 
175 template <class Impl>
176 void
178 {
179  using namespace Stats;
180  iqInstsAdded
181  .name(name() + ".iqInstsAdded")
182  .desc("Number of instructions added to the IQ (excludes non-spec)")
183  .prereq(iqInstsAdded);
184 
185  iqNonSpecInstsAdded
186  .name(name() + ".iqNonSpecInstsAdded")
187  .desc("Number of non-speculative instructions added to the IQ")
188  .prereq(iqNonSpecInstsAdded);
189 
190  iqInstsIssued
191  .name(name() + ".iqInstsIssued")
192  .desc("Number of instructions issued")
193  .prereq(iqInstsIssued);
194 
195  iqIntInstsIssued
196  .name(name() + ".iqIntInstsIssued")
197  .desc("Number of integer instructions issued")
198  .prereq(iqIntInstsIssued);
199 
200  iqFloatInstsIssued
201  .name(name() + ".iqFloatInstsIssued")
202  .desc("Number of float instructions issued")
203  .prereq(iqFloatInstsIssued);
204 
205  iqBranchInstsIssued
206  .name(name() + ".iqBranchInstsIssued")
207  .desc("Number of branch instructions issued")
208  .prereq(iqBranchInstsIssued);
209 
210  iqMemInstsIssued
211  .name(name() + ".iqMemInstsIssued")
212  .desc("Number of memory instructions issued")
213  .prereq(iqMemInstsIssued);
214 
215  iqMiscInstsIssued
216  .name(name() + ".iqMiscInstsIssued")
217  .desc("Number of miscellaneous instructions issued")
218  .prereq(iqMiscInstsIssued);
219 
220  iqSquashedInstsIssued
221  .name(name() + ".iqSquashedInstsIssued")
222  .desc("Number of squashed instructions issued")
223  .prereq(iqSquashedInstsIssued);
224 
225  iqSquashedInstsExamined
226  .name(name() + ".iqSquashedInstsExamined")
227  .desc("Number of squashed instructions iterated over during squash;"
228  " mainly for profiling")
229  .prereq(iqSquashedInstsExamined);
230 
231  iqSquashedOperandsExamined
232  .name(name() + ".iqSquashedOperandsExamined")
233  .desc("Number of squashed operands that are examined and possibly "
234  "removed from graph")
235  .prereq(iqSquashedOperandsExamined);
236 
237  iqSquashedNonSpecRemoved
238  .name(name() + ".iqSquashedNonSpecRemoved")
239  .desc("Number of squashed non-spec instructions that were removed")
240  .prereq(iqSquashedNonSpecRemoved);
241 /*
242  queueResDist
243  .init(Num_OpClasses, 0, 99, 2)
244  .name(name() + ".IQ:residence:")
245  .desc("cycles from dispatch to issue")
246  .flags(total | pdf | cdf )
247  ;
248  for (int i = 0; i < Num_OpClasses; ++i) {
249  queueResDist.subname(i, opClassStrings[i]);
250  }
251 */
252  numIssuedDist
253  .init(0,totalWidth,1)
254  .name(name() + ".issued_per_cycle")
255  .desc("Number of insts issued each cycle")
256  .flags(pdf)
257  ;
258 /*
259  dist_unissued
260  .init(Num_OpClasses+2)
261  .name(name() + ".unissued_cause")
262  .desc("Reason ready instruction not issued")
263  .flags(pdf | dist)
264  ;
265  for (int i=0; i < (Num_OpClasses + 2); ++i) {
266  dist_unissued.subname(i, unissued_names[i]);
267  }
268 */
269  statIssuedInstType
270  .init(numThreads,Enums::Num_OpClass)
271  .name(name() + ".FU_type")
272  .desc("Type of FU issued")
273  .flags(total | pdf | dist)
274  ;
275  statIssuedInstType.ysubnames(Enums::OpClassStrings);
276 
277  //
278  // How long did instructions for a particular FU type wait prior to issue
279  //
280 /*
281  issueDelayDist
282  .init(Num_OpClasses,0,99,2)
283  .name(name() + ".")
284  .desc("cycles from operands ready to issue")
285  .flags(pdf | cdf)
286  ;
287 
288  for (int i=0; i<Num_OpClasses; ++i) {
289  std::stringstream subname;
290  subname << opClassStrings[i] << "_delay";
291  issueDelayDist.subname(i, subname.str());
292  }
293 */
294  issueRate
295  .name(name() + ".rate")
296  .desc("Inst issue rate")
297  .flags(total)
298  ;
299  issueRate = iqInstsIssued / cpu->numCycles;
300 
301  statFuBusy
302  .init(Num_OpClasses)
303  .name(name() + ".fu_full")
304  .desc("attempts to use FU when none available")
305  .flags(pdf | dist)
306  ;
307  for (int i=0; i < Num_OpClasses; ++i) {
308  statFuBusy.subname(i, Enums::OpClassStrings[i]);
309  }
310 
311  fuBusy
312  .init(numThreads)
313  .name(name() + ".fu_busy_cnt")
314  .desc("FU busy when requested")
315  .flags(total)
316  ;
317 
318  fuBusyRate
319  .name(name() + ".fu_busy_rate")
320  .desc("FU busy rate (busy events/executed inst)")
321  .flags(total)
322  ;
323  fuBusyRate = fuBusy / iqInstsIssued;
324 
325  for (ThreadID tid = 0; tid < numThreads; tid++) {
326  // Tell mem dependence unit to reg stats as well.
327  memDepUnit[tid].regStats();
328  }
329 
330  intInstQueueReads
331  .name(name() + ".int_inst_queue_reads")
332  .desc("Number of integer instruction queue reads")
333  .flags(total);
334 
335  intInstQueueWrites
336  .name(name() + ".int_inst_queue_writes")
337  .desc("Number of integer instruction queue writes")
338  .flags(total);
339 
340  intInstQueueWakeupAccesses
341  .name(name() + ".int_inst_queue_wakeup_accesses")
342  .desc("Number of integer instruction queue wakeup accesses")
343  .flags(total);
344 
345  fpInstQueueReads
346  .name(name() + ".fp_inst_queue_reads")
347  .desc("Number of floating instruction queue reads")
348  .flags(total);
349 
350  fpInstQueueWrites
351  .name(name() + ".fp_inst_queue_writes")
352  .desc("Number of floating instruction queue writes")
353  .flags(total);
354 
355  fpInstQueueWakeupAccesses
356  .name(name() + ".fp_inst_queue_wakeup_accesses")
357  .desc("Number of floating instruction queue wakeup accesses")
358  .flags(total);
359 
360  vecInstQueueReads
361  .name(name() + ".vec_inst_queue_reads")
362  .desc("Number of vector instruction queue reads")
363  .flags(total);
364 
365  vecInstQueueWrites
366  .name(name() + ".vec_inst_queue_writes")
367  .desc("Number of vector instruction queue writes")
368  .flags(total);
369 
370  vecInstQueueWakeupAccesses
371  .name(name() + ".vec_inst_queue_wakeup_accesses")
372  .desc("Number of vector instruction queue wakeup accesses")
373  .flags(total);
374 
375  intAluAccesses
376  .name(name() + ".int_alu_accesses")
377  .desc("Number of integer alu accesses")
378  .flags(total);
379 
380  fpAluAccesses
381  .name(name() + ".fp_alu_accesses")
382  .desc("Number of floating point alu accesses")
383  .flags(total);
384 
385  vecAluAccesses
386  .name(name() + ".vec_alu_accesses")
387  .desc("Number of vector alu accesses")
388  .flags(total);
389 
390 }
391 
392 template <class Impl>
393 void
395 {
396  //Initialize thread IQ counts
397  for (ThreadID tid = 0; tid < Impl::MaxThreads; tid++) {
398  count[tid] = 0;
399  instList[tid].clear();
400  }
401 
402  // Initialize the number of free IQ entries.
403  freeEntries = numEntries;
404 
405  // Note that in actuality, the registers corresponding to the logical
406  // registers start off as ready. However this doesn't matter for the
407  // IQ as the instruction should have been correctly told if those
408  // registers are ready in rename. Thus it can all be initialized as
409  // unready.
410  for (int i = 0; i < numPhysRegs; ++i) {
411  regScoreboard[i] = false;
412  }
413 
414  for (ThreadID tid = 0; tid < Impl::MaxThreads; ++tid) {
415  squashedSeqNum[tid] = 0;
416  }
417 
418  for (int i = 0; i < Num_OpClasses; ++i) {
419  while (!readyInsts[i].empty())
420  readyInsts[i].pop();
421  queueOnList[i] = false;
422  readyIt[i] = listOrder.end();
423  }
424  nonSpecInsts.clear();
425  listOrder.clear();
426  deferredMemInsts.clear();
427  blockedMemInsts.clear();
428  retryMemInsts.clear();
429  wbOutstanding = 0;
430 }
431 
432 template <class Impl>
433 void
435 {
436  activeThreads = at_ptr;
437 }
438 
439 template <class Impl>
440 void
442 {
443  issueToExecuteQueue = i2e_ptr;
444 }
445 
446 template <class Impl>
447 void
449 {
450  timeBuffer = tb_ptr;
451 
452  fromCommit = timeBuffer->getWire(-commitToIEWDelay);
453 }
454 
455 template <class Impl>
456 bool
458 {
459  bool drained = dependGraph.empty() &&
460  instsToExecute.empty() &&
461  wbOutstanding == 0;
462  for (ThreadID tid = 0; tid < numThreads; ++tid)
463  drained = drained && memDepUnit[tid].isDrained();
464 
465  return drained;
466 }
467 
468 template <class Impl>
469 void
471 {
472  assert(dependGraph.empty());
473  assert(instsToExecute.empty());
474  for (ThreadID tid = 0; tid < numThreads; ++tid)
475  memDepUnit[tid].drainSanityCheck();
476 }
477 
478 template <class Impl>
479 void
481 {
482  resetState();
483 }
484 
485 template <class Impl>
486 int
488 {
489  if (iqPolicy == SMTQueuePolicy::Partitioned) {
490  return numEntries / num_threads;
491  } else {
492  return 0;
493  }
494 }
495 
496 
497 template <class Impl>
498 void
500 {
501  if (iqPolicy != SMTQueuePolicy::Dynamic || numThreads > 1) {
502  int active_threads = activeThreads->size();
503 
504  list<ThreadID>::iterator threads = activeThreads->begin();
505  list<ThreadID>::iterator end = activeThreads->end();
506 
507  while (threads != end) {
508  ThreadID tid = *threads++;
509 
510  if (iqPolicy == SMTQueuePolicy::Partitioned) {
511  maxEntries[tid] = numEntries / active_threads;
512  } else if (iqPolicy == SMTQueuePolicy::Threshold &&
513  active_threads == 1) {
514  maxEntries[tid] = numEntries;
515  }
516  }
517  }
518 }
519 
520 template <class Impl>
521 unsigned
523 {
524  return freeEntries;
525 }
526 
527 template <class Impl>
528 unsigned
530 {
531  return maxEntries[tid] - count[tid];
532 }
533 
534 // Might want to do something more complex if it knows how many instructions
535 // will be issued this cycle.
536 template <class Impl>
537 bool
539 {
540  if (freeEntries == 0) {
541  return(true);
542  } else {
543  return(false);
544  }
545 }
546 
547 template <class Impl>
548 bool
550 {
551  if (numFreeEntries(tid) == 0) {
552  return(true);
553  } else {
554  return(false);
555  }
556 }
557 
558 template <class Impl>
559 bool
561 {
562  if (!listOrder.empty()) {
563  return true;
564  }
565 
566  for (int i = 0; i < Num_OpClasses; ++i) {
567  if (!readyInsts[i].empty()) {
568  return true;
569  }
570  }
571 
572  return false;
573 }
574 
575 template <class Impl>
576 void
578 {
579  if (new_inst->isFloating()) {
580  fpInstQueueWrites++;
581  } else if (new_inst->isVector()) {
582  vecInstQueueWrites++;
583  } else {
584  intInstQueueWrites++;
585  }
586  // Make sure the instruction is valid
587  assert(new_inst);
588 
589  DPRINTF(IQ, "Adding instruction [sn:%llu] PC %s to the IQ.\n",
590  new_inst->seqNum, new_inst->pcState());
591 
592  assert(freeEntries != 0);
593 
594  instList[new_inst->threadNumber].push_back(new_inst);
595 
596  --freeEntries;
597 
598  new_inst->setInIQ();
599 
600  // Look through its source registers (physical regs), and mark any
601  // dependencies.
602  addToDependents(new_inst);
603 
604  // Have this instruction set itself as the producer of its destination
605  // register(s).
606  addToProducers(new_inst);
607 
608  if (new_inst->isMemRef()) {
609  memDepUnit[new_inst->threadNumber].insert(new_inst);
610  } else {
611  addIfReady(new_inst);
612  }
613 
614  ++iqInstsAdded;
615 
616  count[new_inst->threadNumber]++;
617 
618  assert(freeEntries == (numEntries - countInsts()));
619 }
620 
621 template <class Impl>
622 void
624 {
625  // @todo: Clean up this code; can do it by setting inst as unable
626  // to issue, then calling normal insert on the inst.
627  if (new_inst->isFloating()) {
628  fpInstQueueWrites++;
629  } else if (new_inst->isVector()) {
630  vecInstQueueWrites++;
631  } else {
632  intInstQueueWrites++;
633  }
634 
635  assert(new_inst);
636 
637  nonSpecInsts[new_inst->seqNum] = new_inst;
638 
639  DPRINTF(IQ, "Adding non-speculative instruction [sn:%llu] PC %s "
640  "to the IQ.\n",
641  new_inst->seqNum, new_inst->pcState());
642 
643  assert(freeEntries != 0);
644 
645  instList[new_inst->threadNumber].push_back(new_inst);
646 
647  --freeEntries;
648 
649  new_inst->setInIQ();
650 
651  // Have this instruction set itself as the producer of its destination
652  // register(s).
653  addToProducers(new_inst);
654 
655  // If it's a memory instruction, add it to the memory dependency
656  // unit.
657  if (new_inst->isMemRef()) {
658  memDepUnit[new_inst->threadNumber].insertNonSpec(new_inst);
659  }
660 
661  ++iqNonSpecInstsAdded;
662 
663  count[new_inst->threadNumber]++;
664 
665  assert(freeEntries == (numEntries - countInsts()));
666 }
667 
668 template <class Impl>
669 void
671 {
672  memDepUnit[barr_inst->threadNumber].insertBarrier(barr_inst);
673 
674  insertNonSpec(barr_inst);
675 }
676 
677 template <class Impl>
678 typename Impl::DynInstPtr
680 {
681  assert(!instsToExecute.empty());
682  DynInstPtr inst = std::move(instsToExecute.front());
683  instsToExecute.pop_front();
684  if (inst->isFloating()) {
685  fpInstQueueReads++;
686  } else if (inst->isVector()) {
687  vecInstQueueReads++;
688  } else {
689  intInstQueueReads++;
690  }
691  return inst;
692 }
693 
694 template <class Impl>
695 void
697 {
698  assert(!readyInsts[op_class].empty());
699 
700  ListOrderEntry queue_entry;
701 
702  queue_entry.queueType = op_class;
703 
704  queue_entry.oldestInst = readyInsts[op_class].top()->seqNum;
705 
706  ListOrderIt list_it = listOrder.begin();
707  ListOrderIt list_end_it = listOrder.end();
708 
709  while (list_it != list_end_it) {
710  if ((*list_it).oldestInst > queue_entry.oldestInst) {
711  break;
712  }
713 
714  list_it++;
715  }
716 
717  readyIt[op_class] = listOrder.insert(list_it, queue_entry);
718  queueOnList[op_class] = true;
719 }
720 
721 template <class Impl>
722 void
724 {
725  // Get iterator of next item on the list
726  // Delete the original iterator
727  // Determine if the next item is either the end of the list or younger
728  // than the new instruction. If so, then add in a new iterator right here.
729  // If not, then move along.
730  ListOrderEntry queue_entry;
731  OpClass op_class = (*list_order_it).queueType;
732  ListOrderIt next_it = list_order_it;
733 
734  ++next_it;
735 
736  queue_entry.queueType = op_class;
737  queue_entry.oldestInst = readyInsts[op_class].top()->seqNum;
738 
739  while (next_it != listOrder.end() &&
740  (*next_it).oldestInst < queue_entry.oldestInst) {
741  ++next_it;
742  }
743 
744  readyIt[op_class] = listOrder.insert(next_it, queue_entry);
745 }
746 
747 template <class Impl>
748 void
750 {
751  DPRINTF(IQ, "Processing FU completion [sn:%llu]\n", inst->seqNum);
752  assert(!cpu->switchedOut());
753  // The CPU could have been sleeping until this op completed (*extremely*
754  // long latency op). Wake it if it was. This may be overkill.
755  --wbOutstanding;
756  iewStage->wakeCPU();
757 
758  if (fu_idx > -1)
759  fuPool->freeUnitNextCycle(fu_idx);
760 
761  // @todo: Ensure that these FU Completions happen at the beginning
762  // of a cycle, otherwise they could add too many instructions to
763  // the queue.
764  issueToExecuteQueue->access(-1)->size++;
765  instsToExecute.push_back(inst);
766 }
767 
768 // @todo: Figure out a better way to remove the squashed items from the
769 // lists. Checking the top item of each list to see if it's squashed
770 // wastes time and forces jumps.
771 template <class Impl>
772 void
774 {
775  DPRINTF(IQ, "Attempting to schedule ready instructions from "
776  "the IQ.\n");
777 
778  IssueStruct *i2e_info = issueToExecuteQueue->access(0);
779 
780  DynInstPtr mem_inst;
781  while (mem_inst = std::move(getDeferredMemInstToExecute())) {
782  addReadyMemInst(mem_inst);
783  }
784 
785  // See if any cache blocked instructions are able to be executed
786  while (mem_inst = std::move(getBlockedMemInstToExecute())) {
787  addReadyMemInst(mem_inst);
788  }
789 
790  // Have iterator to head of the list
791  // While I haven't exceeded bandwidth or reached the end of the list,
792  // Try to get a FU that can do what this op needs.
793  // If successful, change the oldestInst to the new top of the list, put
794  // the queue in the proper place in the list.
795  // Increment the iterator.
796  // This will avoid trying to schedule a certain op class if there are no
797  // FUs that handle it.
798  int total_issued = 0;
799  ListOrderIt order_it = listOrder.begin();
800  ListOrderIt order_end_it = listOrder.end();
801 
802  while (total_issued < totalWidth && order_it != order_end_it) {
803  OpClass op_class = (*order_it).queueType;
804 
805  assert(!readyInsts[op_class].empty());
806 
807  DynInstPtr issuing_inst = readyInsts[op_class].top();
808 
809  if (issuing_inst->isFloating()) {
810  fpInstQueueReads++;
811  } else if (issuing_inst->isVector()) {
812  vecInstQueueReads++;
813  } else {
814  intInstQueueReads++;
815  }
816 
817  assert(issuing_inst->seqNum == (*order_it).oldestInst);
818 
819  if (issuing_inst->isSquashed()) {
820  readyInsts[op_class].pop();
821 
822  if (!readyInsts[op_class].empty()) {
823  moveToYoungerInst(order_it);
824  } else {
825  readyIt[op_class] = listOrder.end();
826  queueOnList[op_class] = false;
827  }
828 
829  listOrder.erase(order_it++);
830 
831  ++iqSquashedInstsIssued;
832 
833  continue;
834  }
835 
836  int idx = FUPool::NoCapableFU;
837  Cycles op_latency = Cycles(1);
838  ThreadID tid = issuing_inst->threadNumber;
839 
840  if (op_class != No_OpClass) {
841  idx = fuPool->getUnit(op_class);
842  if (issuing_inst->isFloating()) {
843  fpAluAccesses++;
844  } else if (issuing_inst->isVector()) {
845  vecAluAccesses++;
846  } else {
847  intAluAccesses++;
848  }
849  if (idx > FUPool::NoFreeFU) {
850  op_latency = fuPool->getOpLatency(op_class);
851  }
852  }
853 
854  // If we have an instruction that doesn't require a FU, or a
855  // valid FU, then schedule for execution.
856  if (idx != FUPool::NoFreeFU) {
857  if (op_latency == Cycles(1)) {
858  i2e_info->size++;
859  instsToExecute.push_back(issuing_inst);
860 
861  // Add the FU onto the list of FU's to be freed next
862  // cycle if we used one.
863  if (idx >= 0)
864  fuPool->freeUnitNextCycle(idx);
865  } else {
866  bool pipelined = fuPool->isPipelined(op_class);
867  // Generate completion event for the FU
868  ++wbOutstanding;
869  FUCompletion *execution = new FUCompletion(issuing_inst,
870  idx, this);
871 
872  cpu->schedule(execution,
873  cpu->clockEdge(Cycles(op_latency - 1)));
874 
875  if (!pipelined) {
876  // If FU isn't pipelined, then it must be freed
877  // upon the execution completing.
878  execution->setFreeFU();
879  } else {
880  // Add the FU onto the list of FU's to be freed next cycle.
881  fuPool->freeUnitNextCycle(idx);
882  }
883  }
884 
885  DPRINTF(IQ, "Thread %i: Issuing instruction PC %s "
886  "[sn:%llu]\n",
887  tid, issuing_inst->pcState(),
888  issuing_inst->seqNum);
889 
890  readyInsts[op_class].pop();
891 
892  if (!readyInsts[op_class].empty()) {
893  moveToYoungerInst(order_it);
894  } else {
895  readyIt[op_class] = listOrder.end();
896  queueOnList[op_class] = false;
897  }
898 
899  issuing_inst->setIssued();
900  ++total_issued;
901 
902 #if TRACING_ON
903  issuing_inst->issueTick = curTick() - issuing_inst->fetchTick;
904 #endif
905 
906  if (!issuing_inst->isMemRef()) {
907  // Memory instructions can not be freed from the IQ until they
908  // complete.
909  ++freeEntries;
910  count[tid]--;
911  issuing_inst->clearInIQ();
912  } else {
913  memDepUnit[tid].issue(issuing_inst);
914  }
915 
916  listOrder.erase(order_it++);
917  statIssuedInstType[tid][op_class]++;
918  } else {
919  statFuBusy[op_class]++;
920  fuBusy[tid]++;
921  ++order_it;
922  }
923  }
924 
925  numIssuedDist.sample(total_issued);
926  iqInstsIssued+= total_issued;
927 
928  // If we issued any instructions, tell the CPU we had activity.
929  // @todo If the way deferred memory instructions are handeled due to
930  // translation changes then the deferredMemInsts condition should be removed
931  // from the code below.
932  if (total_issued || !retryMemInsts.empty() || !deferredMemInsts.empty()) {
933  cpu->activityThisCycle();
934  } else {
935  DPRINTF(IQ, "Not able to schedule any instructions.\n");
936  }
937 }
938 
939 template <class Impl>
940 void
942 {
943  DPRINTF(IQ, "Marking nonspeculative instruction [sn:%llu] as ready "
944  "to execute.\n", inst);
945 
946  NonSpecMapIt inst_it = nonSpecInsts.find(inst);
947 
948  assert(inst_it != nonSpecInsts.end());
949 
950  ThreadID tid = (*inst_it).second->threadNumber;
951 
952  (*inst_it).second->setAtCommit();
953 
954  (*inst_it).second->setCanIssue();
955 
956  if (!(*inst_it).second->isMemRef()) {
957  addIfReady((*inst_it).second);
958  } else {
959  memDepUnit[tid].nonSpecInstReady((*inst_it).second);
960  }
961 
962  (*inst_it).second = NULL;
963 
964  nonSpecInsts.erase(inst_it);
965 }
966 
967 template <class Impl>
968 void
970 {
971  DPRINTF(IQ, "[tid:%i] Committing instructions older than [sn:%llu]\n",
972  tid,inst);
973 
974  ListIt iq_it = instList[tid].begin();
975 
976  while (iq_it != instList[tid].end() &&
977  (*iq_it)->seqNum <= inst) {
978  ++iq_it;
979  instList[tid].pop_front();
980  }
981 
982  assert(freeEntries == (numEntries - countInsts()));
983 }
984 
985 template <class Impl>
986 int
988 {
989  int dependents = 0;
990 
991  // The instruction queue here takes care of both floating and int ops
992  if (completed_inst->isFloating()) {
993  fpInstQueueWakeupAccesses++;
994  } else if (completed_inst->isVector()) {
995  vecInstQueueWakeupAccesses++;
996  } else {
997  intInstQueueWakeupAccesses++;
998  }
999 
1000  DPRINTF(IQ, "Waking dependents of completed instruction.\n");
1001 
1002  assert(!completed_inst->isSquashed());
1003 
1004  // Tell the memory dependence unit to wake any dependents on this
1005  // instruction if it is a memory instruction. Also complete the memory
1006  // instruction at this point since we know it executed without issues.
1007  ThreadID tid = completed_inst->threadNumber;
1008  if (completed_inst->isMemRef()) {
1009  memDepUnit[tid].completeInst(completed_inst);
1010 
1011  DPRINTF(IQ, "Completing mem instruction PC: %s [sn:%llu]\n",
1012  completed_inst->pcState(), completed_inst->seqNum);
1013 
1014  ++freeEntries;
1015  completed_inst->memOpDone(true);
1016  count[tid]--;
1017  } else if (completed_inst->isMemBarrier() ||
1018  completed_inst->isWriteBarrier()) {
1019  // Completes a non mem ref barrier
1020  memDepUnit[tid].completeInst(completed_inst);
1021  }
1022 
1023  for (int dest_reg_idx = 0;
1024  dest_reg_idx < completed_inst->numDestRegs();
1025  dest_reg_idx++)
1026  {
1027  PhysRegIdPtr dest_reg =
1028  completed_inst->renamedDestRegIdx(dest_reg_idx);
1029 
1030  // Special case of uniq or control registers. They are not
1031  // handled by the IQ and thus have no dependency graph entry.
1032  if (dest_reg->isFixedMapping()) {
1033  DPRINTF(IQ, "Reg %d [%s] is part of a fix mapping, skipping\n",
1034  dest_reg->index(), dest_reg->className());
1035  continue;
1036  }
1037 
1038  // Avoid waking up dependents if the register is pinned
1039  dest_reg->decrNumPinnedWritesToComplete();
1040  if (dest_reg->isPinned())
1041  completed_inst->setPinnedRegsWritten();
1042 
1043  if (dest_reg->getNumPinnedWritesToComplete() != 0) {
1044  DPRINTF(IQ, "Reg %d [%s] is pinned, skipping\n",
1045  dest_reg->index(), dest_reg->className());
1046  continue;
1047  }
1048 
1049  DPRINTF(IQ, "Waking any dependents on register %i (%s).\n",
1050  dest_reg->index(),
1051  dest_reg->className());
1052 
1053  //Go through the dependency chain, marking the registers as
1054  //ready within the waiting instructions.
1055  DynInstPtr dep_inst = dependGraph.pop(dest_reg->flatIndex());
1056 
1057  while (dep_inst) {
1058  DPRINTF(IQ, "Waking up a dependent instruction, [sn:%llu] "
1059  "PC %s.\n", dep_inst->seqNum, dep_inst->pcState());
1060 
1061  // Might want to give more information to the instruction
1062  // so that it knows which of its source registers is
1063  // ready. However that would mean that the dependency
1064  // graph entries would need to hold the src_reg_idx.
1065  dep_inst->markSrcRegReady();
1066 
1067  addIfReady(dep_inst);
1068 
1069  dep_inst = dependGraph.pop(dest_reg->flatIndex());
1070 
1071  ++dependents;
1072  }
1073 
1074  // Reset the head node now that all of its dependents have
1075  // been woken up.
1076  assert(dependGraph.empty(dest_reg->flatIndex()));
1077  dependGraph.clearInst(dest_reg->flatIndex());
1078 
1079  // Mark the scoreboard as having that register ready.
1080  regScoreboard[dest_reg->flatIndex()] = true;
1081  }
1082  return dependents;
1083 }
1084 
1085 template <class Impl>
1086 void
1088 {
1089  OpClass op_class = ready_inst->opClass();
1090 
1091  readyInsts[op_class].push(ready_inst);
1092 
1093  // Will need to reorder the list if either a queue is not on the list,
1094  // or it has an older instruction than last time.
1095  if (!queueOnList[op_class]) {
1096  addToOrderList(op_class);
1097  } else if (readyInsts[op_class].top()->seqNum <
1098  (*readyIt[op_class]).oldestInst) {
1099  listOrder.erase(readyIt[op_class]);
1100  addToOrderList(op_class);
1101  }
1102 
1103  DPRINTF(IQ, "Instruction is ready to issue, putting it onto "
1104  "the ready list, PC %s opclass:%i [sn:%llu].\n",
1105  ready_inst->pcState(), op_class, ready_inst->seqNum);
1106 }
1107 
1108 template <class Impl>
1109 void
1111 {
1112  DPRINTF(IQ, "Rescheduling mem inst [sn:%llu]\n", resched_inst->seqNum);
1113 
1114  // Reset DTB translation state
1115  resched_inst->translationStarted(false);
1116  resched_inst->translationCompleted(false);
1117 
1118  resched_inst->clearCanIssue();
1119  memDepUnit[resched_inst->threadNumber].reschedule(resched_inst);
1120 }
1121 
1122 template <class Impl>
1123 void
1125 {
1126  memDepUnit[replay_inst->threadNumber].replay();
1127 }
1128 
1129 template <class Impl>
1130 void
1132 {
1133  deferredMemInsts.push_back(deferred_inst);
1134 }
1135 
1136 template <class Impl>
1137 void
1139 {
1140  blocked_inst->clearIssued();
1141  blocked_inst->clearCanIssue();
1142  blockedMemInsts.push_back(blocked_inst);
1143 }
1144 
1145 template <class Impl>
1146 void
1148 {
1149  retryMemInsts.splice(retryMemInsts.end(), blockedMemInsts);
1150  // Get the CPU ticking again
1151  cpu->wakeCPU();
1152 }
1153 
1154 template <class Impl>
1155 typename Impl::DynInstPtr
1157 {
1158  for (ListIt it = deferredMemInsts.begin(); it != deferredMemInsts.end();
1159  ++it) {
1160  if ((*it)->translationCompleted() || (*it)->isSquashed()) {
1161  DynInstPtr mem_inst = std::move(*it);
1162  deferredMemInsts.erase(it);
1163  return mem_inst;
1164  }
1165  }
1166  return nullptr;
1167 }
1168 
1169 template <class Impl>
1170 typename Impl::DynInstPtr
1172 {
1173  if (retryMemInsts.empty()) {
1174  return nullptr;
1175  } else {
1176  DynInstPtr mem_inst = std::move(retryMemInsts.front());
1177  retryMemInsts.pop_front();
1178  return mem_inst;
1179  }
1180 }
1181 
1182 template <class Impl>
1183 void
1185  const DynInstPtr &faulting_load)
1186 {
1187  intInstQueueWrites++;
1188  memDepUnit[store->threadNumber].violation(store, faulting_load);
1189 }
1190 
1191 template <class Impl>
1192 void
1194 {
1195  DPRINTF(IQ, "[tid:%i] Starting to squash instructions in "
1196  "the IQ.\n", tid);
1197 
1198  // Read instruction sequence number of last instruction out of the
1199  // time buffer.
1200  squashedSeqNum[tid] = fromCommit->commitInfo[tid].doneSeqNum;
1201 
1202  doSquash(tid);
1203 
1204  // Also tell the memory dependence unit to squash.
1205  memDepUnit[tid].squash(squashedSeqNum[tid], tid);
1206 }
1207 
1208 template <class Impl>
1209 void
1211 {
1212  // Start at the tail.
1213  ListIt squash_it = instList[tid].end();
1214  --squash_it;
1215 
1216  DPRINTF(IQ, "[tid:%i] Squashing until sequence number %i!\n",
1217  tid, squashedSeqNum[tid]);
1218 
1219  // Squash any instructions younger than the squashed sequence number
1220  // given.
1221  while (squash_it != instList[tid].end() &&
1222  (*squash_it)->seqNum > squashedSeqNum[tid]) {
1223 
1224  DynInstPtr squashed_inst = (*squash_it);
1225  if (squashed_inst->isFloating()) {
1226  fpInstQueueWrites++;
1227  } else if (squashed_inst->isVector()) {
1228  vecInstQueueWrites++;
1229  } else {
1230  intInstQueueWrites++;
1231  }
1232 
1233  // Only handle the instruction if it actually is in the IQ and
1234  // hasn't already been squashed in the IQ.
1235  if (squashed_inst->threadNumber != tid ||
1236  squashed_inst->isSquashedInIQ()) {
1237  --squash_it;
1238  continue;
1239  }
1240 
1241  if (!squashed_inst->isIssued() ||
1242  (squashed_inst->isMemRef() &&
1243  !squashed_inst->memOpDone())) {
1244 
1245  DPRINTF(IQ, "[tid:%i] Instruction [sn:%llu] PC %s squashed.\n",
1246  tid, squashed_inst->seqNum, squashed_inst->pcState());
1247 
1248  bool is_acq_rel = squashed_inst->isMemBarrier() &&
1249  (squashed_inst->isLoad() ||
1250  (squashed_inst->isStore() &&
1251  !squashed_inst->isStoreConditional()));
1252 
1253  // Remove the instruction from the dependency list.
1254  if (is_acq_rel ||
1255  (!squashed_inst->isNonSpeculative() &&
1256  !squashed_inst->isStoreConditional() &&
1257  !squashed_inst->isAtomic() &&
1258  !squashed_inst->isMemBarrier() &&
1259  !squashed_inst->isWriteBarrier())) {
1260 
1261  for (int src_reg_idx = 0;
1262  src_reg_idx < squashed_inst->numSrcRegs();
1263  src_reg_idx++)
1264  {
1265  PhysRegIdPtr src_reg =
1266  squashed_inst->renamedSrcRegIdx(src_reg_idx);
1267 
1268  // Only remove it from the dependency graph if it
1269  // was placed there in the first place.
1270 
1271  // Instead of doing a linked list traversal, we
1272  // can just remove these squashed instructions
1273  // either at issue time, or when the register is
1274  // overwritten. The only downside to this is it
1275  // leaves more room for error.
1276 
1277  if (!squashed_inst->isReadySrcRegIdx(src_reg_idx) &&
1278  !src_reg->isFixedMapping()) {
1279  dependGraph.remove(src_reg->flatIndex(),
1280  squashed_inst);
1281  }
1282 
1283  ++iqSquashedOperandsExamined;
1284  }
1285 
1286  } else if (!squashed_inst->isStoreConditional() ||
1287  !squashed_inst->isCompleted()) {
1288  NonSpecMapIt ns_inst_it =
1289  nonSpecInsts.find(squashed_inst->seqNum);
1290 
1291  // we remove non-speculative instructions from
1292  // nonSpecInsts already when they are ready, and so we
1293  // cannot always expect to find them
1294  if (ns_inst_it == nonSpecInsts.end()) {
1295  // loads that became ready but stalled on a
1296  // blocked cache are alreayd removed from
1297  // nonSpecInsts, and have not faulted
1298  assert(squashed_inst->getFault() != NoFault ||
1299  squashed_inst->isMemRef());
1300  } else {
1301 
1302  (*ns_inst_it).second = NULL;
1303 
1304  nonSpecInsts.erase(ns_inst_it);
1305 
1306  ++iqSquashedNonSpecRemoved;
1307  }
1308  }
1309 
1310  // Might want to also clear out the head of the dependency graph.
1311 
1312  // Mark it as squashed within the IQ.
1313  squashed_inst->setSquashedInIQ();
1314 
1315  // @todo: Remove this hack where several statuses are set so the
1316  // inst will flow through the rest of the pipeline.
1317  squashed_inst->setIssued();
1318  squashed_inst->setCanCommit();
1319  squashed_inst->clearInIQ();
1320 
1321  //Update Thread IQ Count
1322  count[squashed_inst->threadNumber]--;
1323 
1324  ++freeEntries;
1325  }
1326 
1327  // IQ clears out the heads of the dependency graph only when
1328  // instructions reach writeback stage. If an instruction is squashed
1329  // before writeback stage, its head of dependency graph would not be
1330  // cleared out; it holds the instruction's DynInstPtr. This prevents
1331  // freeing the squashed instruction's DynInst.
1332  // Thus, we need to manually clear out the squashed instructions' heads
1333  // of dependency graph.
1334  for (int dest_reg_idx = 0;
1335  dest_reg_idx < squashed_inst->numDestRegs();
1336  dest_reg_idx++)
1337  {
1338  PhysRegIdPtr dest_reg =
1339  squashed_inst->renamedDestRegIdx(dest_reg_idx);
1340  if (dest_reg->isFixedMapping()){
1341  continue;
1342  }
1343  assert(dependGraph.empty(dest_reg->flatIndex()));
1344  dependGraph.clearInst(dest_reg->flatIndex());
1345  }
1346  instList[tid].erase(squash_it--);
1347  ++iqSquashedInstsExamined;
1348  }
1349 }
1350 
1351 template <class Impl>
1352 bool
1354 {
1355  // Loop through the instruction's source registers, adding
1356  // them to the dependency list if they are not ready.
1357  int8_t total_src_regs = new_inst->numSrcRegs();
1358  bool return_val = false;
1359 
1360  for (int src_reg_idx = 0;
1361  src_reg_idx < total_src_regs;
1362  src_reg_idx++)
1363  {
1364  // Only add it to the dependency graph if it's not ready.
1365  if (!new_inst->isReadySrcRegIdx(src_reg_idx)) {
1366  PhysRegIdPtr src_reg = new_inst->renamedSrcRegIdx(src_reg_idx);
1367 
1368  // Check the IQ's scoreboard to make sure the register
1369  // hasn't become ready while the instruction was in flight
1370  // between stages. Only if it really isn't ready should
1371  // it be added to the dependency graph.
1372  if (src_reg->isFixedMapping()) {
1373  continue;
1374  } else if (!regScoreboard[src_reg->flatIndex()]) {
1375  DPRINTF(IQ, "Instruction PC %s has src reg %i (%s) that "
1376  "is being added to the dependency chain.\n",
1377  new_inst->pcState(), src_reg->index(),
1378  src_reg->className());
1379 
1380  dependGraph.insert(src_reg->flatIndex(), new_inst);
1381 
1382  // Change the return value to indicate that something
1383  // was added to the dependency graph.
1384  return_val = true;
1385  } else {
1386  DPRINTF(IQ, "Instruction PC %s has src reg %i (%s) that "
1387  "became ready before it reached the IQ.\n",
1388  new_inst->pcState(), src_reg->index(),
1389  src_reg->className());
1390  // Mark a register ready within the instruction.
1391  new_inst->markSrcRegReady(src_reg_idx);
1392  }
1393  }
1394  }
1395 
1396  return return_val;
1397 }
1398 
1399 template <class Impl>
1400 void
1402 {
1403  // Nothing really needs to be marked when an instruction becomes
1404  // the producer of a register's value, but for convenience a ptr
1405  // to the producing instruction will be placed in the head node of
1406  // the dependency links.
1407  int8_t total_dest_regs = new_inst->numDestRegs();
1408 
1409  for (int dest_reg_idx = 0;
1410  dest_reg_idx < total_dest_regs;
1411  dest_reg_idx++)
1412  {
1413  PhysRegIdPtr dest_reg = new_inst->renamedDestRegIdx(dest_reg_idx);
1414 
1415  // Some registers have fixed mapping, and there is no need to track
1416  // dependencies as these instructions must be executed at commit.
1417  if (dest_reg->isFixedMapping()) {
1418  continue;
1419  }
1420 
1421  if (!dependGraph.empty(dest_reg->flatIndex())) {
1422  dependGraph.dump();
1423  panic("Dependency graph %i (%s) (flat: %i) not empty!",
1424  dest_reg->index(), dest_reg->className(),
1425  dest_reg->flatIndex());
1426  }
1427 
1428  dependGraph.setInst(dest_reg->flatIndex(), new_inst);
1429 
1430  // Mark the scoreboard to say it's not yet ready.
1431  regScoreboard[dest_reg->flatIndex()] = false;
1432  }
1433 }
1434 
1435 template <class Impl>
1436 void
1438 {
1439  // If the instruction now has all of its source registers
1440  // available, then add it to the list of ready instructions.
1441  if (inst->readyToIssue()) {
1442 
1443  //Add the instruction to the proper ready list.
1444  if (inst->isMemRef()) {
1445 
1446  DPRINTF(IQ, "Checking if memory instruction can issue.\n");
1447 
1448  // Message to the mem dependence unit that this instruction has
1449  // its registers ready.
1450  memDepUnit[inst->threadNumber].regsReady(inst);
1451 
1452  return;
1453  }
1454 
1455  OpClass op_class = inst->opClass();
1456 
1457  DPRINTF(IQ, "Instruction is ready to issue, putting it onto "
1458  "the ready list, PC %s opclass:%i [sn:%llu].\n",
1459  inst->pcState(), op_class, inst->seqNum);
1460 
1461  readyInsts[op_class].push(inst);
1462 
1463  // Will need to reorder the list if either a queue is not on the list,
1464  // or it has an older instruction than last time.
1465  if (!queueOnList[op_class]) {
1466  addToOrderList(op_class);
1467  } else if (readyInsts[op_class].top()->seqNum <
1468  (*readyIt[op_class]).oldestInst) {
1469  listOrder.erase(readyIt[op_class]);
1470  addToOrderList(op_class);
1471  }
1472  }
1473 }
1474 
1475 template <class Impl>
1476 int
1478 {
1479  return numEntries - freeEntries;
1480 }
1481 
1482 template <class Impl>
1483 void
1485 {
1486  for (int i = 0; i < Num_OpClasses; ++i) {
1487  cprintf("Ready list %i size: %i\n", i, readyInsts[i].size());
1488 
1489  cprintf("\n");
1490  }
1491 
1492  cprintf("Non speculative list size: %i\n", nonSpecInsts.size());
1493 
1494  NonSpecMapIt non_spec_it = nonSpecInsts.begin();
1495  NonSpecMapIt non_spec_end_it = nonSpecInsts.end();
1496 
1497  cprintf("Non speculative list: ");
1498 
1499  while (non_spec_it != non_spec_end_it) {
1500  cprintf("%s [sn:%llu]", (*non_spec_it).second->pcState(),
1501  (*non_spec_it).second->seqNum);
1502  ++non_spec_it;
1503  }
1504 
1505  cprintf("\n");
1506 
1507  ListOrderIt list_order_it = listOrder.begin();
1508  ListOrderIt list_order_end_it = listOrder.end();
1509  int i = 1;
1510 
1511  cprintf("List order: ");
1512 
1513  while (list_order_it != list_order_end_it) {
1514  cprintf("%i OpClass:%i [sn:%llu] ", i, (*list_order_it).queueType,
1515  (*list_order_it).oldestInst);
1516 
1517  ++list_order_it;
1518  ++i;
1519  }
1520 
1521  cprintf("\n");
1522 }
1523 
1524 
1525 template <class Impl>
1526 void
1528 {
1529  for (ThreadID tid = 0; tid < numThreads; ++tid) {
1530  int num = 0;
1531  int valid_num = 0;
1532  ListIt inst_list_it = instList[tid].begin();
1533 
1534  while (inst_list_it != instList[tid].end()) {
1535  cprintf("Instruction:%i\n", num);
1536  if (!(*inst_list_it)->isSquashed()) {
1537  if (!(*inst_list_it)->isIssued()) {
1538  ++valid_num;
1539  cprintf("Count:%i\n", valid_num);
1540  } else if ((*inst_list_it)->isMemRef() &&
1541  !(*inst_list_it)->memOpDone()) {
1542  // Loads that have not been marked as executed
1543  // still count towards the total instructions.
1544  ++valid_num;
1545  cprintf("Count:%i\n", valid_num);
1546  }
1547  }
1548 
1549  cprintf("PC: %s\n[sn:%llu]\n[tid:%i]\n"
1550  "Issued:%i\nSquashed:%i\n",
1551  (*inst_list_it)->pcState(),
1552  (*inst_list_it)->seqNum,
1553  (*inst_list_it)->threadNumber,
1554  (*inst_list_it)->isIssued(),
1555  (*inst_list_it)->isSquashed());
1556 
1557  if ((*inst_list_it)->isMemRef()) {
1558  cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone());
1559  }
1560 
1561  cprintf("\n");
1562 
1563  inst_list_it++;
1564  ++num;
1565  }
1566  }
1567 
1568  cprintf("Insts to Execute list:\n");
1569 
1570  int num = 0;
1571  int valid_num = 0;
1572  ListIt inst_list_it = instsToExecute.begin();
1573 
1574  while (inst_list_it != instsToExecute.end())
1575  {
1576  cprintf("Instruction:%i\n",
1577  num);
1578  if (!(*inst_list_it)->isSquashed()) {
1579  if (!(*inst_list_it)->isIssued()) {
1580  ++valid_num;
1581  cprintf("Count:%i\n", valid_num);
1582  } else if ((*inst_list_it)->isMemRef() &&
1583  !(*inst_list_it)->memOpDone()) {
1584  // Loads that have not been marked as executed
1585  // still count towards the total instructions.
1586  ++valid_num;
1587  cprintf("Count:%i\n", valid_num);
1588  }
1589  }
1590 
1591  cprintf("PC: %s\n[sn:%llu]\n[tid:%i]\n"
1592  "Issued:%i\nSquashed:%i\n",
1593  (*inst_list_it)->pcState(),
1594  (*inst_list_it)->seqNum,
1595  (*inst_list_it)->threadNumber,
1596  (*inst_list_it)->isIssued(),
1597  (*inst_list_it)->isSquashed());
1598 
1599  if ((*inst_list_it)->isMemRef()) {
1600  cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone());
1601  }
1602 
1603  cprintf("\n");
1604 
1605  inst_list_it++;
1606  ++num;
1607  }
1608 }
1609 
1610 #endif//__CPU_O3_INST_QUEUE_IMPL_HH__
Num_OpClasses
static const OpClass Num_OpClasses
Definition: op_class.hh:105
InstructionQueue::addIfReady
void addIfReady(const DynInstPtr &inst)
Moves an instruction to the ready queue if it is ready.
Definition: inst_queue_impl.hh:1437
InstructionQueue::ListOrderEntry::queueType
OpClass queueType
Definition: inst_queue.hh:364
InstructionQueue::ListOrderEntry::oldestInst
InstSeqNum oldestInst
Definition: inst_queue.hh:365
InstructionQueue::takeOverFrom
void takeOverFrom()
Takes over execution from another CPU's thread.
Definition: inst_queue_impl.hh:480
InstructionQueue::iewStage
IEW * iewStage
Pointer to IEW stage.
Definition: inst_queue.hh:285
InstructionQueue::wakeDependents
int wakeDependents(const DynInstPtr &completed_inst)
Wakes all dependents of a completed instruction.
Definition: inst_queue_impl.hh:987
InstructionQueue::commit
void commit(const InstSeqNum &inst, ThreadID tid=0)
Commits all instructions up to and including the given sequence number, for a specific thread.
Definition: inst_queue_impl.hh:969
InstructionQueue::FUCompletion::setFreeFU
void setFreeFU()
Definition: inst_queue.hh:120
InstructionQueue::name
std::string name() const
Returns the name of the IQ.
Definition: inst_queue_impl.hh:170
ArmISA::i
Bitfield< 7 > i
Definition: miscregs_types.hh:63
InstructionQueue::getDeferredMemInstToExecute
DynInstPtr getDeferredMemInstToExecute()
Gets a memory instruction that was referred due to a delayed DTB translation if it is now ready to ex...
Definition: inst_queue_impl.hh:1156
InstructionQueue::squash
void squash(ThreadID tid)
Squashes instructions for a thread.
Definition: inst_queue_impl.hh:1193
InstructionQueue::getBlockedMemInstToExecute
DynInstPtr getBlockedMemInstToExecute()
Gets a memory instruction that was blocked on the cache.
Definition: inst_queue_impl.hh:1171
ThreadID
int16_t ThreadID
Thread index/ID type.
Definition: types.hh:227
InstructionQueue::FUCompletion::process
virtual void process()
Definition: inst_queue_impl.hh:70
InstructionQueue::commitToIEWDelay
Cycles commitToIEWDelay
Delay between commit stage and the IQ.
Definition: inst_queue.hh:435
InstructionQueue::iqPolicy
SMTQueuePolicy iqPolicy
IQ sharing policy for SMT.
Definition: inst_queue.hh:403
InstructionQueue::ListOrderIt
std::list< ListOrderEntry >::iterator ListOrderIt
Definition: inst_queue.hh:377
InstructionQueue::resetEntries
void resetEntries()
Resets max entries for all threads.
Definition: inst_queue_impl.hh:499
PhysRegId::flatIndex
const PhysRegIndex & flatIndex() const
Flat index accessor.
Definition: reg_class.hh:305
InstructionQueue::resetState
void resetState()
Resets all instruction queue state.
Definition: inst_queue_impl.hh:394
sc_dt::list
static scfx_rep_node * list
Definition: scfx_rep.cc:368
InstructionQueue::entryAmount
int entryAmount(ThreadID num_threads)
Number of entries needed for given amount of threads.
Definition: inst_queue_impl.hh:487
InstructionQueue::deferMemInst
void deferMemInst(const DynInstPtr &deferred_inst)
Defers a memory instruction when its DTB translation incurs a hw page table walk.
Definition: inst_queue_impl.hh:1131
InstructionQueue::NonSpecMapIt
std::map< InstSeqNum, DynInstPtr >::iterator NonSpecMapIt
Definition: inst_queue.hh:360
top
Definition: test.h:61
InstructionQueue::drainSanityCheck
void drainSanityCheck() const
Perform sanity checks after a drain.
Definition: inst_queue_impl.hh:470
InstructionQueue::~InstructionQueue
~InstructionQueue()
Destructs the IQ.
Definition: inst_queue_impl.hh:159
InstructionQueue::countInsts
int countInsts()
Debugging function to count how many entries are in the IQ.
Definition: inst_queue_impl.hh:1477
InstructionQueue::dependGraph
DependencyGraph< DynInstPtr > dependGraph
Definition: inst_queue.hh:396
InstructionQueue::ListIt
std::list< DynInstPtr >::iterator ListIt
Definition: inst_queue.hh:94
X86ISA::count
count
Definition: misc.hh:703
InstructionQueue::maxEntries
unsigned maxEntries[Impl::MaxThreads]
Max IQ Entries Per Thread.
Definition: inst_queue.hh:415
InstructionQueue::blockMemInst
void blockMemInst(const DynInstPtr &blocked_inst)
Defers a memory instruction when it is cache blocked.
Definition: inst_queue_impl.hh:1138
PhysRegId::isFixedMapping
bool isFixedMapping() const
Returns true if this register is always associated to the same architectural register.
Definition: reg_class.hh:299
InstructionQueue::moveToYoungerInst
void moveToYoungerInst(ListOrderIt age_order_it)
Called when the oldest instruction has been removed from a ready queue; this places that ready queue ...
Definition: inst_queue_impl.hh:723
InstructionQueue::cacheUnblocked
void cacheUnblocked()
Notify instruction queue that a previous blockage has resolved.
Definition: inst_queue_impl.hh:1147
InstructionQueue::setIssueToExecuteQueue
void setIssueToExecuteQueue(TimeBuffer< IssueStruct > *i2eQueue)
Sets the timer buffer between issue and execute.
Definition: inst_queue_impl.hh:441
InstructionQueue::numPhysRegs
unsigned numPhysRegs
The number of physical registers in the CPU.
Definition: inst_queue.hh:427
TimeBuffer< IssueStruct >
InstructionQueue::processFUCompletion
void processFUCompletion(const DynInstPtr &inst, int fu_idx)
Process FU completion event.
Definition: inst_queue_impl.hh:749
InstructionQueue::cpu
O3CPU * cpu
Pointer to the CPU.
Definition: inst_queue.hh:279
InstructionQueue::fuPool
FUPool * fuPool
Function unit pool.
Definition: inst_queue.hh:304
PhysRegId::index
const RegIndex & index() const
Visible RegId methods.
Definition: reg_class.hh:173
InstructionQueue::totalWidth
unsigned totalWidth
The total number of instructions that can be issued in one cycle.
Definition: inst_queue.hh:424
InstructionQueue::ListOrderEntry
Entry for the list age ordering by op class.
Definition: inst_queue.hh:363
IssueStruct::size
int size
Definition: comm.hh:108
FUPool::NoCapableFU
static constexpr auto NoCapableFU
Definition: fu_pool.hh:135
Event
Definition: eventq.hh:246
InstructionQueue::memDepUnit
MemDepUnit memDepUnit[Impl::MaxThreads]
The memory dependence unit, which tracks/predicts memory dependences between instructions.
Definition: inst_queue.hh:290
InstructionQueue::insert
void insert(const DynInstPtr &new_inst)
Inserts a new instruction into the IQ.
Definition: inst_queue_impl.hh:577
InstructionQueue::regStats
void regStats()
Registers statistics.
Definition: inst_queue_impl.hh:177
cprintf
void cprintf(const char *format, const Args &...args)
Definition: cprintf.hh:152
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:234
InstructionQueue::addToProducers
void addToProducers(const DynInstPtr &new_inst)
Adds an instruction to the dependency graph, as a producer.
Definition: inst_queue_impl.hh:1401
InstructionQueue::isDrained
bool isDrained() const
Determine if we are drained.
Definition: inst_queue_impl.hh:457
InstructionQueue::dumpLists
void dumpLists()
Debugging function to dump all the list sizes, as well as print out the list of nonspeculative instru...
Definition: inst_queue_impl.hh:1484
InstructionQueue::numThreads
ThreadID numThreads
Number of Total Threads.
Definition: inst_queue.hh:406
ArmISA::NumVecElemPerVecReg
constexpr unsigned NumVecElemPerVecReg
Definition: registers.hh:66
IssueStruct
Definition: comm.hh:105
InstructionQueue::InstructionQueue
InstructionQueue(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params)
Constructs an IQ.
Definition: inst_queue_impl.hh:85
fu_pool.hh
InstructionQueue::replayMemInst
void replayMemInst(const DynInstPtr &replay_inst)
Replays a memory instruction.
Definition: inst_queue_impl.hh:1124
InstructionQueue::dumpInsts
void dumpInsts()
Debugging function to dump out all instructions that are in the IQ.
Definition: inst_queue_impl.hh:1527
InstructionQueue::insertNonSpec
void insertNonSpec(const DynInstPtr &new_inst)
Inserts a new, non-speculative instruction into the IQ.
Definition: inst_queue_impl.hh:623
InstSeqNum
uint64_t InstSeqNum
Definition: inst_seq.hh:37
NoFault
constexpr decltype(nullptr) NoFault
Definition: types.hh:245
InstructionQueue::doSquash
void doSquash(ThreadID tid)
Does the actual squashing.
Definition: inst_queue_impl.hh:1210
MemDepUnit::setIQ
void setIQ(InstructionQueue< Impl > *iq_ptr)
Sets the pointer to the IQ.
Definition: mem_dep_unit_impl.hh:164
PhysRegId::decrNumPinnedWritesToComplete
void decrNumPinnedWritesToComplete()
Definition: reg_class.hh:342
InstructionQueue::scheduleReadyInsts
void scheduleReadyInsts()
Schedules ready instructions, adding the ready ones (oldest first) to the queue to execute.
Definition: inst_queue_impl.hh:773
core.hh
InstructionQueue::DynInstPtr
Impl::DynInstPtr DynInstPtr
Definition: inst_queue.hh:86
Stats::dist
const FlagsType dist
Print the distribution.
Definition: info.hh:55
name
const std::string & name()
Definition: trace.cc:50
InstructionQueue::scheduleNonSpec
void scheduleNonSpec(const InstSeqNum &inst)
Schedules a single specific non-speculative instruction.
Definition: inst_queue_impl.hh:941
InstructionQueue::violation
void violation(const DynInstPtr &store, const DynInstPtr &faulting_load)
Indicates an ordering violation between a store and a load.
Definition: inst_queue_impl.hh:1184
InstructionQueue::IEW
Impl::CPUPol::IEW IEW
Definition: inst_queue.hh:88
InstructionQueue::FUCompletion::FUCompletion
FUCompletion(const DynInstPtr &_inst, int fu_idx, InstructionQueue< Impl > *iq_ptr)
Construct a FU completion event.
Definition: inst_queue_impl.hh:61
InstructionQueue::FUCompletion::description
virtual const char * description() const
Return a C string describing the event.
Definition: inst_queue_impl.hh:79
PhysRegId::className
const char * className() const
Return a const char* with the register class name.
Definition: reg_class.hh:202
InstructionQueue::numEntries
unsigned numEntries
The number of entries in the instruction queue.
Definition: inst_queue.hh:421
PhysRegId::isPinned
bool isPinned() const
Definition: reg_class.hh:330
InstructionQueue::getInstToExecute
DynInstPtr getInstToExecute()
Returns the oldest scheduled instruction, and removes it from the list of instructions waiting to exe...
Definition: inst_queue_impl.hh:679
Stats::pdf
const FlagsType pdf
Print the percent of the total that this entry represents.
Definition: info.hh:51
PhysRegId::getNumPinnedWritesToComplete
int getNumPinnedWritesToComplete() const
Definition: reg_class.hh:332
InstructionQueue
A standard instruction queue class.
Definition: inst_queue.hh:81
InstructionQueue::setActiveThreads
void setActiveThreads(std::list< ThreadID > *at_ptr)
Sets active threads list.
Definition: inst_queue_impl.hh:434
InstructionQueue::addToOrderList
void addToOrderList(OpClass op_class)
Add an op class to the age order list.
Definition: inst_queue_impl.hh:696
InstructionQueue::insertBarrier
void insertBarrier(const DynInstPtr &barr_inst)
Inserts a memory or write barrier into the IQ to make sure loads and stores are ordered properly.
Definition: inst_queue_impl.hh:670
logging.hh
Cycles
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:83
MemDepUnit::init
void init(DerivO3CPUParams *params, ThreadID tid)
Initializes the unit with parameters and a thread id.
Definition: mem_dep_unit_impl.hh:95
PhysRegId
Physical register ID.
Definition: reg_class.hh:223
InstructionQueue::regScoreboard
std::vector< bool > regScoreboard
A cache of the recently woken registers.
Definition: inst_queue.hh:446
Stats
Definition: statistics.cc:61
inst_queue.hh
InstructionQueue::O3CPU
Impl::O3CPU O3CPU
Definition: inst_queue.hh:85
InstructionQueue::addToDependents
bool addToDependents(const DynInstPtr &new_inst)
Adds an instruction to the dependency graph, as a consumer.
Definition: inst_queue_impl.hh:1353
InstructionQueue::numFreeEntries
unsigned numFreeEntries()
Returns total number of free entries.
Definition: inst_queue_impl.hh:522
InstructionQueue::FUCompletion
FU completion event class.
Definition: inst_queue.hh:97
std::list
STL list class.
Definition: stl.hh:51
InstructionQueue::rescheduleMemInst
void rescheduleMemInst(const DynInstPtr &resched_inst)
Reschedules a memory instruction.
Definition: inst_queue_impl.hh:1110
FUPool::NoFreeFU
static constexpr auto NoFreeFU
Definition: fu_pool.hh:136
InstructionQueue::setTimeBuffer
void setTimeBuffer(TimeBuffer< TimeStruct > *tb_ptr)
Sets the global time buffer.
Definition: inst_queue_impl.hh:448
Stats::total
const FlagsType total
Print the total.
Definition: info.hh:49
InstructionQueue::isFull
bool isFull()
Returns whether or not the IQ is full.
Definition: inst_queue_impl.hh:538
InstructionQueue::hasReadyInsts
bool hasReadyInsts()
Returns if there are any ready instructions in the IQ.
Definition: inst_queue_impl.hh:560
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:171
curTick
Tick curTick()
The current simulated tick.
Definition: core.hh:45
InstructionQueue::addReadyMemInst
void addReadyMemInst(const DynInstPtr &ready_inst)
Adds a ready memory instruction to the ready list.
Definition: inst_queue_impl.hh:1087
TimeBuffer::getWire
wire getWire(int idx)
Definition: timebuf.hh:229

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