blob: 9419fe4b4a6eebfff04a2bc241c4e433d2444804 [file] [log] [blame]
Andrea Di Biagio35622482018-03-22 10:19:20 +00001//===--------------------- TimelineView.cpp ---------------------*- C++ -*-===//
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9/// \brief
10///
11/// This file implements the TimelineView interface.
12///
13//===----------------------------------------------------------------------===//
14
15#include "TimelineView.h"
16
17using namespace llvm;
18
19namespace mca {
20
21void TimelineView::initialize(unsigned MaxIterations) {
22 unsigned NumInstructions =
23 AsmSequence.getNumIterations() * AsmSequence.size();
24 if (!MaxIterations)
25 MaxIterations = DEFAULT_ITERATIONS;
26 unsigned NumEntries =
27 std::min(NumInstructions, MaxIterations * AsmSequence.size());
28 Timeline.resize(NumEntries);
29 TimelineViewEntry NullTVEntry = {0, 0, 0, 0, 0};
30 std::fill(Timeline.begin(), Timeline.end(), NullTVEntry);
31
32 WaitTime.resize(AsmSequence.size());
33 WaitTimeEntry NullWTEntry = {0, 0, 0, 0};
34 std::fill(WaitTime.begin(), WaitTime.end(), NullWTEntry);
35}
36
Clement Courbet844f22d2018-03-13 13:11:01 +000037void TimelineView::onInstructionEvent(const HWInstructionEvent &Event) {
38 if (CurrentCycle >= MaxCycle || Event.Index >= Timeline.size())
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000039 return;
Clement Courbet844f22d2018-03-13 13:11:01 +000040 switch (Event.Type) {
41 case HWInstructionEvent::Retired: {
42 TimelineViewEntry &TVEntry = Timeline[Event.Index];
43 TVEntry.CycleRetired = CurrentCycle;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000044
Clement Courbet844f22d2018-03-13 13:11:01 +000045 // Update the WaitTime entry which corresponds to this Index.
46 WaitTimeEntry &WTEntry = WaitTime[Event.Index % AsmSequence.size()];
47 WTEntry.Executions++;
48 WTEntry.CyclesSpentInSchedulerQueue +=
49 TVEntry.CycleIssued - TVEntry.CycleDispatched;
50 assert(TVEntry.CycleDispatched <= TVEntry.CycleReady);
51 WTEntry.CyclesSpentInSQWhileReady +=
52 TVEntry.CycleIssued - TVEntry.CycleReady;
53 WTEntry.CyclesSpentAfterWBAndBeforeRetire +=
54 (TVEntry.CycleRetired - 1) - TVEntry.CycleExecuted;
55 break;
56 }
57 case HWInstructionEvent::Ready:
58 Timeline[Event.Index].CycleReady = CurrentCycle;
59 break;
60 case HWInstructionEvent::Issued:
61 Timeline[Event.Index].CycleIssued = CurrentCycle;
62 break;
63 case HWInstructionEvent::Executed:
64 Timeline[Event.Index].CycleExecuted = CurrentCycle;
65 break;
66 case HWInstructionEvent::Dispatched:
67 Timeline[Event.Index].CycleDispatched = CurrentCycle;
68 break;
69 default:
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000070 return;
Clement Courbet844f22d2018-03-13 13:11:01 +000071 }
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000072 LastCycle = std::max(LastCycle, CurrentCycle);
73}
74
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000075void TimelineView::printWaitTimeEntry(raw_string_ostream &OS,
76 const WaitTimeEntry &Entry,
77 unsigned SourceIndex) const {
78 OS << SourceIndex << '.';
79 if (SourceIndex < 10)
80 OS << " ";
81 else if (SourceIndex < 100)
82 OS << " ";
83 else if (SourceIndex < 1000)
84 OS << " ";
85 else
86 OS << ' ';
87
88 if (Entry.Executions == 0) {
89 OS << " - - - - ";
90 } else {
91 double AverageTime1, AverageTime2, AverageTime3;
92 unsigned Executions = Entry.Executions;
93 AverageTime1 = (double)Entry.CyclesSpentInSchedulerQueue / Executions;
94 AverageTime2 = (double)Entry.CyclesSpentInSQWhileReady / Executions;
95 AverageTime3 = (double)Entry.CyclesSpentAfterWBAndBeforeRetire / Executions;
96 if (Executions < 10)
97 OS << ' ' << Executions << " ";
98 else if (Executions < 100)
99 OS << ' ' << Executions << " ";
100 else
101 OS << Executions << " ";
102
103 OS << format("%.1f", AverageTime1);
104 if (AverageTime1 < 10.0)
105 OS << " ";
106 else if (AverageTime1 < 100.0)
107 OS << " ";
108 else
109 OS << " ";
110
111 OS << format("%.1f", AverageTime2);
112 if (AverageTime2 < 10.0)
113 OS << " ";
114 else if (AverageTime2 < 100.0)
115 OS << " ";
116 else
117 OS << " ";
118
119 OS << format("%.1f", AverageTime3);
120 if (AverageTime3 < 10.0)
121 OS << " ";
122 else if (AverageTime3 < 100.0)
123 OS << ' ';
124 }
125}
126
127void TimelineView::printAverageWaitTimes(raw_ostream &OS) const {
128 if (WaitTime.empty())
129 return;
130
131 std::string Buffer;
132 raw_string_ostream TempStream(Buffer);
133
134 TempStream
135 << "\n\nAverage Wait times (based on the timeline view):\n"
136 << "[0]: Executions\n"
137 << "[1]: Average time spent waiting in a scheduler's queue\n"
138 << "[2]: Average time spent waiting in a scheduler's queue while ready\n"
139 << "[3]: Average time elapsed from WB until retire stage\n\n";
140 TempStream << " [0] [1] [2] [3]\n";
141
142 for (unsigned I = 0, E = WaitTime.size(); I < E; ++I) {
143 printWaitTimeEntry(TempStream, WaitTime[I], I);
144 // Append the instruction info at the end of the line.
145 const MCInst &Inst = AsmSequence.getMCInstFromIndex(I);
146 MCIP.printInst(&Inst, TempStream, "", STI);
147 TempStream << '\n';
148 TempStream.flush();
149 OS << Buffer;
150 Buffer = "";
151 }
152}
153
154void TimelineView::printTimelineViewEntry(raw_string_ostream &OS,
155 const TimelineViewEntry &Entry,
156 unsigned Iteration,
157 unsigned SourceIndex) const {
Hans Wennborg6400c032018-04-09 13:53:41 +0000158 if (SourceIndex == 0)
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000159 OS << '\n';
160 OS << '[' << Iteration << ',' << SourceIndex << "]\t";
161 for (unsigned I = 0, E = Entry.CycleDispatched; I < E; ++I)
162 OS << ((I % 5 == 0) ? '.' : ' ');
163 OS << 'D';
164 if (Entry.CycleDispatched != Entry.CycleExecuted) {
165 // Zero latency instructions have the same value for CycleDispatched,
166 // CycleIssued and CycleExecuted.
Andrea Di Biagio53e6ade2018-03-09 12:50:42 +0000167 for (unsigned I = Entry.CycleDispatched + 1, E = Entry.CycleIssued; I < E;
168 ++I)
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000169 OS << '=';
170 if (Entry.CycleIssued == Entry.CycleExecuted)
171 OS << 'E';
172 else {
173 if (Entry.CycleDispatched != Entry.CycleIssued)
174 OS << 'e';
Andrea Di Biagio53e6ade2018-03-09 12:50:42 +0000175 for (unsigned I = Entry.CycleIssued + 1, E = Entry.CycleExecuted; I < E;
176 ++I)
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000177 OS << 'e';
178 OS << 'E';
179 }
180 }
181
182 for (unsigned I = Entry.CycleExecuted + 1, E = Entry.CycleRetired; I < E; ++I)
183 OS << '-';
184 OS << 'R';
185
186 // Skip other columns.
187 for (unsigned I = Entry.CycleRetired + 1, E = LastCycle; I <= E; ++I)
188 OS << ((I % 5 == 0 || I == LastCycle) ? '.' : ' ');
189}
190
191static void printTimelineHeader(raw_string_ostream &OS, unsigned Cycles) {
192 OS << "\n\nTimeline view:\n";
193 OS << " \t";
194 for (unsigned I = 0; I <= Cycles; ++I) {
195 if (((I / 10) & 1) == 0)
196 OS << ' ';
197 else
198 OS << I % 10;
199 }
200
201 OS << "\nIndex\t";
202 for (unsigned I = 0; I <= Cycles; ++I) {
203 if (((I / 10) & 1) == 0)
204 OS << I % 10;
205 else
206 OS << ' ';
207 }
208 OS << '\n';
209}
210
211void TimelineView::printTimeline(raw_ostream &OS) const {
212 std::string Buffer;
213 raw_string_ostream TempStream(Buffer);
214
215 printTimelineHeader(TempStream, LastCycle);
216 TempStream.flush();
217 OS << Buffer;
218
219 for (unsigned I = 0, E = Timeline.size(); I < E; ++I) {
220 Buffer = "";
221 const TimelineViewEntry &Entry = Timeline[I];
222 if (Entry.CycleRetired == 0)
223 return;
224
225 unsigned Iteration = I / AsmSequence.size();
226 unsigned SourceIndex = I % AsmSequence.size();
227 printTimelineViewEntry(TempStream, Entry, Iteration, SourceIndex);
228 // Append the instruction info at the end of the line.
229 const MCInst &Inst = AsmSequence.getMCInstFromIndex(I);
230 MCIP.printInst(&Inst, TempStream, "", STI);
231 TempStream << '\n';
232 TempStream.flush();
233 OS << Buffer;
234 }
235}
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000236} // namespace mca