1 | //===----------------------- HWEventListener.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 defines the main interface for hardware event listeners. |
11 | /// |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_MCA_HWEVENTLISTENER_H |
15 | #define LLVM_MCA_HWEVENTLISTENER_H |
16 | |
17 | #include "llvm/ADT/ArrayRef.h" |
18 | #include "llvm/MCA/Instruction.h" |
19 | #include "llvm/MCA/Support.h" |
20 | |
21 | namespace llvm { |
22 | namespace mca { |
23 | |
24 | // An HWInstructionEvent represents state changes of instructions that |
25 | // listeners might be interested in. Listeners can choose to ignore any event |
26 | // they are not interested in. |
27 | class HWInstructionEvent { |
28 | public: |
29 | // This is the list of event types that are shared by all targets, that |
30 | // generic subtarget-agnostic classes (e.g., Pipeline, HWInstructionEvent, |
31 | // ...) and generic Views can manipulate. |
32 | // Subtargets are free to define additional event types, that are going to be |
33 | // handled by generic components as opaque values, but can still be |
34 | // emitted by subtarget-specific pipeline stages (e.g., ExecuteStage, |
35 | // DispatchStage, ...) and interpreted by subtarget-specific EventListener |
36 | // implementations. |
37 | enum GenericEventType { |
38 | Invalid = 0, |
39 | // Events generated by the Retire Control Unit. |
40 | Retired, |
41 | // Events generated by the Scheduler. |
42 | Pending, |
43 | Ready, |
44 | Issued, |
45 | Executed, |
46 | // Events generated by the Dispatch logic. |
47 | Dispatched, |
48 | |
49 | LastGenericEventType, |
50 | }; |
51 | |
52 | HWInstructionEvent(unsigned type, const InstRef &Inst) |
53 | : Type(type), IR(Inst) {} |
54 | |
55 | // The event type. The exact meaning depends on the subtarget. |
56 | const unsigned Type; |
57 | |
58 | // The instruction this event was generated for. |
59 | const InstRef &IR; |
60 | }; |
61 | |
62 | // ResourceRef::first is the index of the associated Resource. |
63 | // ResourceRef::second is a bitmask of the referenced sub-unit of the resource. |
64 | using ResourceRef = std::pair<uint64_t, uint64_t>; |
65 | |
66 | using ResourceUse = std::pair<ResourceRef, ReleaseAtCycles>; |
67 | |
68 | class HWInstructionIssuedEvent : public HWInstructionEvent { |
69 | public: |
70 | HWInstructionIssuedEvent(const InstRef &IR, ArrayRef<ResourceUse> UR) |
71 | : HWInstructionEvent(HWInstructionEvent::Issued, IR), UsedResources(UR) {} |
72 | |
73 | ArrayRef<ResourceUse> UsedResources; |
74 | }; |
75 | |
76 | class HWInstructionDispatchedEvent : public HWInstructionEvent { |
77 | public: |
78 | HWInstructionDispatchedEvent(const InstRef &IR, ArrayRef<unsigned> Regs, |
79 | unsigned UOps) |
80 | : HWInstructionEvent(HWInstructionEvent::Dispatched, IR), |
81 | UsedPhysRegs(Regs), MicroOpcodes(UOps) {} |
82 | // Number of physical register allocated for this instruction. There is one |
83 | // entry per register file. |
84 | ArrayRef<unsigned> UsedPhysRegs; |
85 | // Number of micro opcodes dispatched. |
86 | // This field is often set to the total number of micro-opcodes specified by |
87 | // the instruction descriptor of IR. |
88 | // The only exception is when IR declares a number of micro opcodes |
89 | // which exceeds the processor DispatchWidth, and - by construction - it |
90 | // requires multiple cycles to be fully dispatched. In that particular case, |
91 | // the dispatch logic would generate more than one dispatch event (one per |
92 | // cycle), and each event would declare how many micro opcodes are effectively |
93 | // been dispatched to the schedulers. |
94 | unsigned MicroOpcodes; |
95 | }; |
96 | |
97 | class HWInstructionRetiredEvent : public HWInstructionEvent { |
98 | public: |
99 | HWInstructionRetiredEvent(const InstRef &IR, ArrayRef<unsigned> Regs) |
100 | : HWInstructionEvent(HWInstructionEvent::Retired, IR), |
101 | FreedPhysRegs(Regs) {} |
102 | // Number of register writes that have been architecturally committed. There |
103 | // is one entry per register file. |
104 | ArrayRef<unsigned> FreedPhysRegs; |
105 | }; |
106 | |
107 | // A HWStallEvent represents a pipeline stall caused by the lack of hardware |
108 | // resources. |
109 | class HWStallEvent { |
110 | public: |
111 | enum GenericEventType { |
112 | Invalid = 0, |
113 | // Generic stall events generated by the DispatchStage. |
114 | RegisterFileStall, |
115 | RetireControlUnitStall, |
116 | // Generic stall events generated by the Scheduler. |
117 | DispatchGroupStall, |
118 | SchedulerQueueFull, |
119 | LoadQueueFull, |
120 | StoreQueueFull, |
121 | CustomBehaviourStall, |
122 | LastGenericEvent |
123 | }; |
124 | |
125 | HWStallEvent(unsigned type, const InstRef &Inst) : Type(type), IR(Inst) {} |
126 | |
127 | // The exact meaning of the stall event type depends on the subtarget. |
128 | const unsigned Type; |
129 | |
130 | // The instruction this event was generated for. |
131 | const InstRef &IR; |
132 | }; |
133 | |
134 | // A HWPressureEvent describes an increase in backend pressure caused by |
135 | // the presence of data dependencies or unavailability of pipeline resources. |
136 | class HWPressureEvent { |
137 | public: |
138 | enum GenericReason { |
139 | INVALID = 0, |
140 | // Scheduler was unable to issue all the ready instructions because some |
141 | // pipeline resources were unavailable. |
142 | RESOURCES, |
143 | // Instructions could not be issued because of register data dependencies. |
144 | REGISTER_DEPS, |
145 | // Instructions could not be issued because of memory dependencies. |
146 | MEMORY_DEPS |
147 | }; |
148 | |
149 | HWPressureEvent(GenericReason reason, ArrayRef<InstRef> Insts, |
150 | uint64_t Mask = 0) |
151 | : Reason(reason), AffectedInstructions(Insts), ResourceMask(Mask) {} |
152 | |
153 | // Reason for this increase in backend pressure. |
154 | GenericReason Reason; |
155 | |
156 | // Instructions affected (i.e. delayed) by this increase in backend pressure. |
157 | ArrayRef<InstRef> AffectedInstructions; |
158 | |
159 | // A mask of unavailable processor resources. |
160 | const uint64_t ResourceMask; |
161 | }; |
162 | |
163 | class HWEventListener { |
164 | public: |
165 | // Generic events generated by the pipeline. |
166 | virtual void onCycleBegin() {} |
167 | virtual void onCycleEnd() {} |
168 | |
169 | virtual void onEvent(const HWInstructionEvent &Event) {} |
170 | virtual void onEvent(const HWStallEvent &Event) {} |
171 | virtual void onEvent(const HWPressureEvent &Event) {} |
172 | |
173 | virtual void onResourceAvailable(const ResourceRef &RRef) {} |
174 | |
175 | // Events generated by the Scheduler when buffered resources are |
176 | // consumed/freed for an instruction. |
177 | virtual void onReservedBuffers(const InstRef &Inst, |
178 | ArrayRef<unsigned> Buffers) {} |
179 | virtual void onReleasedBuffers(const InstRef &Inst, |
180 | ArrayRef<unsigned> Buffers) {} |
181 | |
182 | virtual ~HWEventListener() = default; |
183 | |
184 | private: |
185 | virtual void anchor(); |
186 | }; |
187 | } // namespace mca |
188 | } // namespace llvm |
189 | |
190 | #endif // LLVM_MCA_HWEVENTLISTENER_H |
191 | |