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 goin 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 HWInstructionEvent(unsigned type,const InstRef & Inst)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 using ResourceRef = std::pair<uint64_t, uint64_t>; 63 using ResourceUse = std::pair<ResourceRef, ResourceCycles>; 64 65 class HWInstructionIssuedEvent : public HWInstructionEvent { 66 public: HWInstructionIssuedEvent(const InstRef & IR,ArrayRef<ResourceUse> UR)67 HWInstructionIssuedEvent(const InstRef &IR, ArrayRef<ResourceUse> UR) 68 : HWInstructionEvent(HWInstructionEvent::Issued, IR), UsedResources(UR) {} 69 70 ArrayRef<ResourceUse> UsedResources; 71 }; 72 73 class HWInstructionDispatchedEvent : public HWInstructionEvent { 74 public: HWInstructionDispatchedEvent(const InstRef & IR,ArrayRef<unsigned> Regs,unsigned UOps)75 HWInstructionDispatchedEvent(const InstRef &IR, ArrayRef<unsigned> Regs, 76 unsigned UOps) 77 : HWInstructionEvent(HWInstructionEvent::Dispatched, IR), 78 UsedPhysRegs(Regs), MicroOpcodes(UOps) {} 79 // Number of physical register allocated for this instruction. There is one 80 // entry per register file. 81 ArrayRef<unsigned> UsedPhysRegs; 82 // Number of micro opcodes dispatched. 83 // This field is often set to the total number of micro-opcodes specified by 84 // the instruction descriptor of IR. 85 // The only exception is when IR declares a number of micro opcodes 86 // which exceeds the processor DispatchWidth, and - by construction - it 87 // requires multiple cycles to be fully dispatched. In that particular case, 88 // the dispatch logic would generate more than one dispatch event (one per 89 // cycle), and each event would declare how many micro opcodes are effectively 90 // been dispatched to the schedulers. 91 unsigned MicroOpcodes; 92 }; 93 94 class HWInstructionRetiredEvent : public HWInstructionEvent { 95 public: HWInstructionRetiredEvent(const InstRef & IR,ArrayRef<unsigned> Regs)96 HWInstructionRetiredEvent(const InstRef &IR, ArrayRef<unsigned> Regs) 97 : HWInstructionEvent(HWInstructionEvent::Retired, IR), 98 FreedPhysRegs(Regs) {} 99 // Number of register writes that have been architecturally committed. There 100 // is one entry per register file. 101 ArrayRef<unsigned> FreedPhysRegs; 102 }; 103 104 // A HWStallEvent represents a pipeline stall caused by the lack of hardware 105 // resources. 106 class HWStallEvent { 107 public: 108 enum GenericEventType { 109 Invalid = 0, 110 // Generic stall events generated by the DispatchStage. 111 RegisterFileStall, 112 RetireControlUnitStall, 113 // Generic stall events generated by the Scheduler. 114 DispatchGroupStall, 115 SchedulerQueueFull, 116 LoadQueueFull, 117 StoreQueueFull, 118 CustomBehaviourStall, 119 LastGenericEvent 120 }; 121 HWStallEvent(unsigned type,const InstRef & Inst)122 HWStallEvent(unsigned type, const InstRef &Inst) : Type(type), IR(Inst) {} 123 124 // The exact meaning of the stall event type depends on the subtarget. 125 const unsigned Type; 126 127 // The instruction this event was generated for. 128 const InstRef &IR; 129 }; 130 131 // A HWPressureEvent describes an increase in backend pressure caused by 132 // the presence of data dependencies or unavailability of pipeline resources. 133 class HWPressureEvent { 134 public: 135 enum GenericReason { 136 INVALID = 0, 137 // Scheduler was unable to issue all the ready instructions because some 138 // pipeline resources were unavailable. 139 RESOURCES, 140 // Instructions could not be issued because of register data dependencies. 141 REGISTER_DEPS, 142 // Instructions could not be issued because of memory dependencies. 143 MEMORY_DEPS 144 }; 145 146 HWPressureEvent(GenericReason reason, ArrayRef<InstRef> Insts, 147 uint64_t Mask = 0) Reason(reason)148 : Reason(reason), AffectedInstructions(Insts), ResourceMask(Mask) {} 149 150 // Reason for this increase in backend pressure. 151 GenericReason Reason; 152 153 // Instructions affected (i.e. delayed) by this increase in backend pressure. 154 ArrayRef<InstRef> AffectedInstructions; 155 156 // A mask of unavailable processor resources. 157 const uint64_t ResourceMask; 158 }; 159 160 class HWEventListener { 161 public: 162 // Generic events generated by the pipeline. onCycleBegin()163 virtual void onCycleBegin() {} onCycleEnd()164 virtual void onCycleEnd() {} 165 onEvent(const HWInstructionEvent & Event)166 virtual void onEvent(const HWInstructionEvent &Event) {} onEvent(const HWStallEvent & Event)167 virtual void onEvent(const HWStallEvent &Event) {} onEvent(const HWPressureEvent & Event)168 virtual void onEvent(const HWPressureEvent &Event) {} 169 onResourceAvailable(const ResourceRef & RRef)170 virtual void onResourceAvailable(const ResourceRef &RRef) {} 171 172 // Events generated by the Scheduler when buffered resources are 173 // consumed/freed for an instruction. onReservedBuffers(const InstRef & Inst,ArrayRef<unsigned> Buffers)174 virtual void onReservedBuffers(const InstRef &Inst, 175 ArrayRef<unsigned> Buffers) {} onReleasedBuffers(const InstRef & Inst,ArrayRef<unsigned> Buffers)176 virtual void onReleasedBuffers(const InstRef &Inst, 177 ArrayRef<unsigned> Buffers) {} 178 179 virtual ~HWEventListener() = default; 180 181 private: 182 virtual void anchor(); 183 }; 184 } // namespace mca 185 } // namespace llvm 186 187 #endif // LLVM_MCA_HWEVENTLISTENER_H 188