1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
| //===----------------------- 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 goin 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;
};
class HWInstructionIssuedEvent : public HWInstructionEvent {
public:
using ResourceRef = std::pair<uint64_t, uint64_t>;
HWInstructionIssuedEvent(const InstRef &IR,
ArrayRef<std::pair<ResourceRef, ResourceCycles>> UR)
: HWInstructionEvent(HWInstructionEvent::Issued, IR), UsedResources(UR) {}
ArrayRef<std::pair<ResourceRef, ResourceCycles>> UsedResources;
};
class HWInstructionDispatchedEvent : public HWInstructionEvent {
public:
HWInstructionDispatchedEvent(const InstRef &IR, ArrayRef<unsigned> 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<unsigned> 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<unsigned> Regs)
: HWInstructionEvent(HWInstructionEvent::Retired, IR),
FreedPhysRegs(Regs) {}
// Number of register writes that have been architecturally committed. There
// is one entry per register file.
ArrayRef<unsigned> 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,
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<InstRef> 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<InstRef> 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) {}
using ResourceRef = std::pair<uint64_t, uint64_t>;
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<unsigned> Buffers) {}
virtual void onReleasedBuffers(const InstRef &Inst,
ArrayRef<unsigned> Buffers) {}
virtual ~HWEventListener() {}
private:
virtual void anchor();
};
} // namespace mca
} // namespace llvm
#endif // LLVM_MCA_HWEVENTLISTENER_H
|