| //===---------------------- RetireControlUnit.h -----------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| /// \file |
| /// |
| /// This file simulates the hardware responsible for retiring instructions. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_TOOLS_LLVM_MCA_RETIRE_CONTROL_UNIT_H |
| #define LLVM_TOOLS_LLVM_MCA_RETIRE_CONTROL_UNIT_H |
| |
| #include "HardwareUnit.h" |
| #include "Instruction.h" |
| #include "llvm/MC/MCSchedule.h" |
| #include <vector> |
| |
| namespace mca { |
| |
| /// This class tracks which instructions are in-flight (i.e., dispatched but not |
| /// retired) in the OoO backend. |
| // |
| /// This class checks on every cycle if/which instructions can be retired. |
| /// Instructions are retired in program order. |
| /// In the event of an instruction being retired, the pipeline that owns |
| /// this RetireControlUnit (RCU) gets notified. |
| /// |
| /// On instruction retired, register updates are all architecturally |
| /// committed, and any physicall registers previously allocated for the |
| /// retired instruction are freed. |
| struct RetireControlUnit : public HardwareUnit { |
| // A RUToken is created by the RCU for every instruction dispatched to the |
| // schedulers. These "tokens" are managed by the RCU in its token Queue. |
| // |
| // On every cycle ('cycleEvent'), the RCU iterates through the token queue |
| // looking for any token with its 'Executed' flag set. If a token has that |
| // flag set, then the instruction has reached the write-back stage and will |
| // be retired by the RCU. |
| // |
| // 'NumSlots' represents the number of entries consumed by the instruction in |
| // the reorder buffer. Those entries will become available again once the |
| // instruction is retired. |
| // |
| // Note that the size of the reorder buffer is defined by the scheduling |
| // model via field 'NumMicroOpBufferSize'. |
| struct RUToken { |
| InstRef IR; |
| unsigned NumSlots; // Slots reserved to this instruction. |
| bool Executed; // True if the instruction is past the WB stage. |
| }; |
| |
| private: |
| unsigned NextAvailableSlotIdx; |
| unsigned CurrentInstructionSlotIdx; |
| unsigned AvailableSlots; |
| unsigned MaxRetirePerCycle; // 0 means no limit. |
| std::vector<RUToken> Queue; |
| |
| public: |
| RetireControlUnit(const llvm::MCSchedModel &SM); |
| |
| bool isFull() const { return !AvailableSlots; } |
| bool isEmpty() const { return AvailableSlots == Queue.size(); } |
| bool isAvailable(unsigned Quantity = 1) const { |
| // Some instructions may declare a number of uOps which exceeds the size |
| // of the reorder buffer. To avoid problems, cap the amount of slots to |
| // the size of the reorder buffer. |
| Quantity = std::min(Quantity, static_cast<unsigned>(Queue.size())); |
| return AvailableSlots >= Quantity; |
| } |
| |
| unsigned getMaxRetirePerCycle() const { return MaxRetirePerCycle; } |
| |
| // Reserves a number of slots, and returns a new token. |
| unsigned reserveSlot(const InstRef &IS, unsigned NumMicroOps); |
| |
| // Return the current token from the RCU's circular token queue. |
| const RUToken &peekCurrentToken() const; |
| |
| // Advance the pointer to the next token in the circular token queue. |
| void consumeCurrentToken(); |
| |
| // Update the RCU token to represent the executed state. |
| void onInstructionExecuted(unsigned TokenID); |
| |
| #ifndef NDEBUG |
| void dump() const; |
| #endif |
| }; |
| |
| } // namespace mca |
| |
| #endif // LLVM_TOOLS_LLVM_MCA_RETIRE_CONTROL_UNIT_H |