RetireControlUnit.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===---------------------- RetireControlUnit.h -----------------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. /// \file
  14. ///
  15. /// This file simulates the hardware responsible for retiring instructions.
  16. ///
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_MCA_HARDWAREUNITS_RETIRECONTROLUNIT_H
  19. #define LLVM_MCA_HARDWAREUNITS_RETIRECONTROLUNIT_H
  20. #include "llvm/MC/MCSchedule.h"
  21. #include "llvm/MCA/HardwareUnits/HardwareUnit.h"
  22. #include "llvm/MCA/Instruction.h"
  23. #include <vector>
  24. namespace llvm {
  25. namespace mca {
  26. /// This class tracks which instructions are in-flight (i.e., dispatched but not
  27. /// retired) in the OoO backend.
  28. //
  29. /// This class checks on every cycle if/which instructions can be retired.
  30. /// Instructions are retired in program order.
  31. /// In the event of an instruction being retired, the pipeline that owns
  32. /// this RetireControlUnit (RCU) gets notified.
  33. ///
  34. /// On instruction retired, register updates are all architecturally
  35. /// committed, and any physicall registers previously allocated for the
  36. /// retired instruction are freed.
  37. struct RetireControlUnit : public HardwareUnit {
  38. // A RUToken is created by the RCU for every instruction dispatched to the
  39. // schedulers. These "tokens" are managed by the RCU in its token Queue.
  40. //
  41. // On every cycle ('cycleEvent'), the RCU iterates through the token queue
  42. // looking for any token with its 'Executed' flag set. If a token has that
  43. // flag set, then the instruction has reached the write-back stage and will
  44. // be retired by the RCU.
  45. //
  46. // 'NumSlots' represents the number of entries consumed by the instruction in
  47. // the reorder buffer. Those entries will become available again once the
  48. // instruction is retired.
  49. //
  50. // Note that the size of the reorder buffer is defined by the scheduling
  51. // model via field 'NumMicroOpBufferSize'.
  52. struct RUToken {
  53. InstRef IR;
  54. unsigned NumSlots; // Slots reserved to this instruction.
  55. bool Executed; // True if the instruction is past the WB stage.
  56. };
  57. private:
  58. unsigned NextAvailableSlotIdx;
  59. unsigned CurrentInstructionSlotIdx;
  60. unsigned NumROBEntries;
  61. unsigned AvailableEntries;
  62. unsigned MaxRetirePerCycle; // 0 means no limit.
  63. std::vector<RUToken> Queue;
  64. unsigned normalizeQuantity(unsigned Quantity) const {
  65. // Some instructions may declare a number of uOps which exceeds the size
  66. // of the reorder buffer. To avoid problems, cap the amount of slots to
  67. // the size of the reorder buffer.
  68. Quantity = std::min(Quantity, NumROBEntries);
  69. // Further normalize the number of micro opcodes for instructions that
  70. // declare zero opcodes. This should match the behavior of method
  71. // reserveSlot().
  72. return std::max(Quantity, 1U);
  73. }
  74. unsigned computeNextSlotIdx() const;
  75. public:
  76. RetireControlUnit(const MCSchedModel &SM);
  77. bool isEmpty() const { return AvailableEntries == NumROBEntries; }
  78. bool isAvailable(unsigned Quantity = 1) const {
  79. return AvailableEntries >= normalizeQuantity(Quantity);
  80. }
  81. unsigned getMaxRetirePerCycle() const { return MaxRetirePerCycle; }
  82. // Reserves a number of slots, and returns a new token reference.
  83. unsigned dispatch(const InstRef &IS);
  84. // Return the current token from the RCU's circular token queue.
  85. const RUToken &getCurrentToken() const;
  86. const RUToken &peekNextToken() const;
  87. // Advance the pointer to the next token in the circular token queue.
  88. void consumeCurrentToken();
  89. // Update the RCU token to represent the executed state.
  90. void onInstructionExecuted(unsigned TokenID);
  91. #ifndef NDEBUG
  92. void dump() const;
  93. #endif
  94. // Assigned to instructions that are not handled by the RCU.
  95. static const unsigned UnhandledTokenID = ~0U;
  96. };
  97. } // namespace mca
  98. } // namespace llvm
  99. #endif // LLVM_MCA_HARDWAREUNITS_RETIRECONTROLUNIT_H
  100. #ifdef __GNUC__
  101. #pragma GCC diagnostic pop
  102. #endif