//===---------------------- 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 temporary registers originally 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 |