RetireControlUnit.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. //===---------------------- RetireControlUnit.cpp ---------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. /// \file
  9. ///
  10. /// This file simulates the hardware responsible for retiring instructions.
  11. ///
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/MCA/HardwareUnits/RetireControlUnit.h"
  14. #include "llvm/Support/Debug.h"
  15. #define DEBUG_TYPE "llvm-mca"
  16. namespace llvm {
  17. namespace mca {
  18. RetireControlUnit::RetireControlUnit(const MCSchedModel &SM)
  19. : NextAvailableSlotIdx(0), CurrentInstructionSlotIdx(0),
  20. AvailableEntries(SM.isOutOfOrder() ? SM.MicroOpBufferSize : 0),
  21. MaxRetirePerCycle(0) {
  22. assert(SM.isOutOfOrder() &&
  23. "RetireControlUnit is not available for in-order processors");
  24. // Check if the scheduling model provides extra information about the machine
  25. // processor. If so, then use that information to set the reorder buffer size
  26. // and the maximum number of instructions retired per cycle.
  27. if (SM.hasExtraProcessorInfo()) {
  28. const MCExtraProcessorInfo &EPI = SM.getExtraProcessorInfo();
  29. if (EPI.ReorderBufferSize)
  30. AvailableEntries = EPI.ReorderBufferSize;
  31. MaxRetirePerCycle = EPI.MaxRetirePerCycle;
  32. }
  33. NumROBEntries = AvailableEntries;
  34. assert(NumROBEntries && "Invalid reorder buffer size!");
  35. Queue.resize(2 * NumROBEntries);
  36. }
  37. // Reserves a number of slots, and returns a new token.
  38. unsigned RetireControlUnit::dispatch(const InstRef &IR) {
  39. const Instruction &Inst = *IR.getInstruction();
  40. unsigned Entries = normalizeQuantity(Inst.getNumMicroOps());
  41. assert((AvailableEntries >= Entries) && "Reorder Buffer unavailable!");
  42. unsigned TokenID = NextAvailableSlotIdx;
  43. Queue[NextAvailableSlotIdx] = {IR, Entries, false};
  44. NextAvailableSlotIdx += std::max(1U, Entries);
  45. NextAvailableSlotIdx %= Queue.size();
  46. assert(TokenID < UnhandledTokenID && "Invalid token ID");
  47. AvailableEntries -= Entries;
  48. return TokenID;
  49. }
  50. const RetireControlUnit::RUToken &RetireControlUnit::getCurrentToken() const {
  51. const RetireControlUnit::RUToken &Current = Queue[CurrentInstructionSlotIdx];
  52. #ifndef NDEBUG
  53. const Instruction *Inst = Current.IR.getInstruction();
  54. assert(Inst && "Invalid RUToken in the RCU queue.");
  55. #endif
  56. return Current;
  57. }
  58. unsigned RetireControlUnit::computeNextSlotIdx() const {
  59. const RetireControlUnit::RUToken &Current = getCurrentToken();
  60. unsigned NextSlotIdx = CurrentInstructionSlotIdx + std::max(1U, Current.NumSlots);
  61. return NextSlotIdx % Queue.size();
  62. }
  63. const RetireControlUnit::RUToken &RetireControlUnit::peekNextToken() const {
  64. return Queue[computeNextSlotIdx()];
  65. }
  66. void RetireControlUnit::consumeCurrentToken() {
  67. RetireControlUnit::RUToken &Current = Queue[CurrentInstructionSlotIdx];
  68. Current.IR.getInstruction()->retire();
  69. // Update the slot index to be the next item in the circular queue.
  70. CurrentInstructionSlotIdx += std::max(1U, Current.NumSlots);
  71. CurrentInstructionSlotIdx %= Queue.size();
  72. AvailableEntries += Current.NumSlots;
  73. Current = { InstRef(), 0U, false };
  74. }
  75. void RetireControlUnit::onInstructionExecuted(unsigned TokenID) {
  76. assert(Queue.size() > TokenID);
  77. assert(Queue[TokenID].IR.getInstruction() && "Instruction was not dispatched!");
  78. assert(Queue[TokenID].Executed == false && "Instruction already executed!");
  79. Queue[TokenID].Executed = true;
  80. }
  81. #ifndef NDEBUG
  82. void RetireControlUnit::dump() const {
  83. dbgs() << "Retire Unit: { Total ROB Entries =" << NumROBEntries
  84. << ", Available ROB entries=" << AvailableEntries << " }\n";
  85. }
  86. #endif
  87. } // namespace mca
  88. } // namespace llvm