1 //===---------------------- RetireControlUnit.h -----------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// \file 10 /// 11 /// This file simulates the hardware responsible for retiring instructions. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_TOOLS_LLVM_MCA_RETIRE_CONTROL_UNIT_H 16 #define LLVM_TOOLS_LLVM_MCA_RETIRE_CONTROL_UNIT_H 17 18 #include "HardwareUnit.h" 19 #include "Instruction.h" 20 #include "llvm/MC/MCSchedule.h" 21 #include <vector> 22 23 namespace mca { 24 25 /// This class tracks which instructions are in-flight (i.e., dispatched but not 26 /// retired) in the OoO backend. 27 // 28 /// This class checks on every cycle if/which instructions can be retired. 29 /// Instructions are retired in program order. 30 /// In the event of an instruction being retired, the pipeline that owns 31 /// this RetireControlUnit (RCU) gets notified. 32 /// 33 /// On instruction retired, register updates are all architecturally 34 /// committed, and any physicall registers previously allocated for the 35 /// retired instruction are freed. 36 struct RetireControlUnit : public HardwareUnit { 37 // A RUToken is created by the RCU for every instruction dispatched to the 38 // schedulers. These "tokens" are managed by the RCU in its token Queue. 39 // 40 // On every cycle ('cycleEvent'), the RCU iterates through the token queue 41 // looking for any token with its 'Executed' flag set. If a token has that 42 // flag set, then the instruction has reached the write-back stage and will 43 // be retired by the RCU. 44 // 45 // 'NumSlots' represents the number of entries consumed by the instruction in 46 // the reorder buffer. Those entries will become available again once the 47 // instruction is retired. 48 // 49 // Note that the size of the reorder buffer is defined by the scheduling 50 // model via field 'NumMicroOpBufferSize'. 51 struct RUToken { 52 InstRef IR; 53 unsigned NumSlots; // Slots reserved to this instruction. 54 bool Executed; // True if the instruction is past the WB stage. 55 }; 56 57 private: 58 unsigned NextAvailableSlotIdx; 59 unsigned CurrentInstructionSlotIdx; 60 unsigned AvailableSlots; 61 unsigned MaxRetirePerCycle; // 0 means no limit. 62 std::vector<RUToken> Queue; 63 64 public: 65 RetireControlUnit(const llvm::MCSchedModel &SM); 66 isFullRetireControlUnit67 bool isFull() const { return !AvailableSlots; } isEmptyRetireControlUnit68 bool isEmpty() const { return AvailableSlots == Queue.size(); } 69 bool isAvailable(unsigned Quantity = 1) const { 70 // Some instructions may declare a number of uOps which exceeds the size 71 // of the reorder buffer. To avoid problems, cap the amount of slots to 72 // the size of the reorder buffer. 73 Quantity = std::min(Quantity, static_cast<unsigned>(Queue.size())); 74 return AvailableSlots >= Quantity; 75 } 76 getMaxRetirePerCycleRetireControlUnit77 unsigned getMaxRetirePerCycle() const { return MaxRetirePerCycle; } 78 79 // Reserves a number of slots, and returns a new token. 80 unsigned reserveSlot(const InstRef &IS, unsigned NumMicroOps); 81 82 // Return the current token from the RCU's circular token queue. 83 const RUToken &peekCurrentToken() const; 84 85 // Advance the pointer to the next token in the circular token queue. 86 void consumeCurrentToken(); 87 88 // Update the RCU token to represent the executed state. 89 void onInstructionExecuted(unsigned TokenID); 90 91 #ifndef NDEBUG 92 void dump() const; 93 #endif 94 }; 95 96 } // namespace mca 97 98 #endif // LLVM_TOOLS_LLVM_MCA_RETIRE_CONTROL_UNIT_H 99