//===----------------------- HWEventListener.h ------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// \file /// /// This file defines the main interface for hardware event listeners. /// //===----------------------------------------------------------------------===// #ifndef LLVM_MCA_HWEVENTLISTENER_H #define LLVM_MCA_HWEVENTLISTENER_H #include "llvm/ADT/ArrayRef.h" #include "llvm/MCA/Instruction.h" #include "llvm/MCA/Support.h" namespace llvm { namespace mca { // An HWInstructionEvent represents state changes of instructions that // listeners might be interested in. Listeners can choose to ignore any event // they are not interested in. class HWInstructionEvent { public: // This is the list of event types that are shared by all targets, that // generic subtarget-agnostic classes (e.g., Pipeline, HWInstructionEvent, // ...) and generic Views can manipulate. // Subtargets are free to define additional event types, that are going to be // handled by generic components as opaque values, but can still be // emitted by subtarget-specific pipeline stages (e.g., ExecuteStage, // DispatchStage, ...) and interpreted by subtarget-specific EventListener // implementations. enum GenericEventType { Invalid = 0, // Events generated by the Retire Control Unit. Retired, // Events generated by the Scheduler. Pending, Ready, Issued, Executed, // Events generated by the Dispatch logic. Dispatched, LastGenericEventType, }; HWInstructionEvent(unsigned type, const InstRef &Inst) : Type(type), IR(Inst) {} // The event type. The exact meaning depends on the subtarget. const unsigned Type; // The instruction this event was generated for. const InstRef &IR; }; // ResourceRef::first is the index of the associated Resource. // ResourceRef::second is a bitmask of the referenced sub-unit of the resource. using ResourceRef = std::pair; using ResourceUse = std::pair; class HWInstructionIssuedEvent : public HWInstructionEvent { public: HWInstructionIssuedEvent(const InstRef &IR, ArrayRef UR) : HWInstructionEvent(HWInstructionEvent::Issued, IR), UsedResources(UR) {} ArrayRef UsedResources; }; class HWInstructionDispatchedEvent : public HWInstructionEvent { public: HWInstructionDispatchedEvent(const InstRef &IR, ArrayRef Regs, unsigned UOps) : HWInstructionEvent(HWInstructionEvent::Dispatched, IR), UsedPhysRegs(Regs), MicroOpcodes(UOps) {} // Number of physical register allocated for this instruction. There is one // entry per register file. ArrayRef UsedPhysRegs; // Number of micro opcodes dispatched. // This field is often set to the total number of micro-opcodes specified by // the instruction descriptor of IR. // The only exception is when IR declares a number of micro opcodes // which exceeds the processor DispatchWidth, and - by construction - it // requires multiple cycles to be fully dispatched. In that particular case, // the dispatch logic would generate more than one dispatch event (one per // cycle), and each event would declare how many micro opcodes are effectively // been dispatched to the schedulers. unsigned MicroOpcodes; }; class HWInstructionRetiredEvent : public HWInstructionEvent { public: HWInstructionRetiredEvent(const InstRef &IR, ArrayRef Regs) : HWInstructionEvent(HWInstructionEvent::Retired, IR), FreedPhysRegs(Regs) {} // Number of register writes that have been architecturally committed. There // is one entry per register file. ArrayRef FreedPhysRegs; }; // A HWStallEvent represents a pipeline stall caused by the lack of hardware // resources. class HWStallEvent { public: enum GenericEventType { Invalid = 0, // Generic stall events generated by the DispatchStage. RegisterFileStall, RetireControlUnitStall, // Generic stall events generated by the Scheduler. DispatchGroupStall, SchedulerQueueFull, LoadQueueFull, StoreQueueFull, CustomBehaviourStall, LastGenericEvent }; HWStallEvent(unsigned type, const InstRef &Inst) : Type(type), IR(Inst) {} // The exact meaning of the stall event type depends on the subtarget. const unsigned Type; // The instruction this event was generated for. const InstRef &IR; }; // A HWPressureEvent describes an increase in backend pressure caused by // the presence of data dependencies or unavailability of pipeline resources. class HWPressureEvent { public: enum GenericReason { INVALID = 0, // Scheduler was unable to issue all the ready instructions because some // pipeline resources were unavailable. RESOURCES, // Instructions could not be issued because of register data dependencies. REGISTER_DEPS, // Instructions could not be issued because of memory dependencies. MEMORY_DEPS }; HWPressureEvent(GenericReason reason, ArrayRef Insts, uint64_t Mask = 0) : Reason(reason), AffectedInstructions(Insts), ResourceMask(Mask) {} // Reason for this increase in backend pressure. GenericReason Reason; // Instructions affected (i.e. delayed) by this increase in backend pressure. ArrayRef AffectedInstructions; // A mask of unavailable processor resources. const uint64_t ResourceMask; }; class HWEventListener { public: // Generic events generated by the pipeline. virtual void onCycleBegin() {} virtual void onCycleEnd() {} virtual void onEvent(const HWInstructionEvent &Event) {} virtual void onEvent(const HWStallEvent &Event) {} virtual void onEvent(const HWPressureEvent &Event) {} virtual void onResourceAvailable(const ResourceRef &RRef) {} // Events generated by the Scheduler when buffered resources are // consumed/freed for an instruction. virtual void onReservedBuffers(const InstRef &Inst, ArrayRef Buffers) {} virtual void onReleasedBuffers(const InstRef &Inst, ArrayRef Buffers) {} virtual ~HWEventListener() = default; private: virtual void anchor(); }; } // namespace mca } // namespace llvm #endif // LLVM_MCA_HWEVENTLISTENER_H