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