1 //===---------------------- RetireControlUnit.h -----------------*- 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 
14 #ifndef LLVM_MCA_HARDWAREUNITS_RETIRECONTROLUNIT_H
15 #define LLVM_MCA_HARDWAREUNITS_RETIRECONTROLUNIT_H
16 
17 #include "llvm/MC/MCSchedule.h"
18 #include "llvm/MCA/HardwareUnits/HardwareUnit.h"
19 #include "llvm/MCA/Instruction.h"
20 #include <vector>
21 
22 namespace llvm {
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 NumROBEntries;
61   unsigned AvailableEntries;
62   unsigned MaxRetirePerCycle; // 0 means no limit.
63   std::vector<RUToken> Queue;
64 
65   unsigned normalizeQuantity(unsigned Quantity) const {
66     // Some instructions may declare a number of uOps which exceeds the size
67     // of the reorder buffer. To avoid problems, cap the amount of slots to
68     // the size of the reorder buffer.
69     Quantity = std::min(Quantity, NumROBEntries);
70 
71     // Further normalize the number of micro opcodes for instructions that
72     // declare zero opcodes. This should match the behavior of method
73     // reserveSlot().
74     return std::max(Quantity, 1U);
75   }
76 
77   unsigned computeNextSlotIdx() const;
78 
79 public:
80   RetireControlUnit(const MCSchedModel &SM);
81 
82   bool isEmpty() const { return AvailableEntries == NumROBEntries; }
83 
84   bool isAvailable(unsigned Quantity = 1) const {
85     return AvailableEntries >= normalizeQuantity(Quantity);
86   }
87 
88   unsigned getMaxRetirePerCycle() const { return MaxRetirePerCycle; }
89 
90   // Reserves a number of slots, and returns a new token reference.
91   unsigned dispatch(const InstRef &IS);
92 
93   // Return the current token from the RCU's circular token queue.
94   const RUToken &getCurrentToken() const;
95 
96   const RUToken &peekNextToken() const;
97 
98   // Advance the pointer to the next token in the circular token queue.
99   void consumeCurrentToken();
100 
101   // Update the RCU token to represent the executed state.
102   void onInstructionExecuted(unsigned TokenID);
103 
104 #ifndef NDEBUG
105   void dump() const;
106 #endif
107 
108   // Assigned to instructions that are not handled by the RCU.
109   static const unsigned UnhandledTokenID = ~0U;
110 };
111 
112 } // namespace mca
113 } // namespace llvm
114 
115 #endif // LLVM_MCA_HARDWAREUNITS_RETIRECONTROLUNIT_H
116