blob: 50d6ebe228877e26e56829d653b707dbeb596b43 [file] [log] [blame]
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +00001//===--------------------- TimelineView.cpp ---------------*- C++ -*-===//
2//
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
37void TimelineView::onInstructionDispatched(unsigned Index) {
38 if (CurrentCycle >= MaxCycle || Index >= Timeline.size())
39 return;
40 Timeline[Index].CycleDispatched = CurrentCycle;
41 LastCycle = std::max(LastCycle, CurrentCycle);
42}
43
44void TimelineView::onInstructionReady(unsigned Index) {
45 if (CurrentCycle >= MaxCycle || Index >= Timeline.size())
46 return;
47 Timeline[Index].CycleReady = CurrentCycle;
48 LastCycle = std::max(LastCycle, CurrentCycle);
49}
50
51void TimelineView::onInstructionIssued(
52 unsigned Index,
53 const ArrayRef<std::pair<ResourceRef, unsigned>> & /* Unused */) {
54 if (CurrentCycle >= MaxCycle || Index >= Timeline.size())
55 return;
56 Timeline[Index].CycleIssued = CurrentCycle;
57 LastCycle = std::max(LastCycle, CurrentCycle);
58}
59
60void TimelineView::onInstructionExecuted(unsigned Index) {
61 if (CurrentCycle >= MaxCycle || Index >= Timeline.size())
62 return;
63 Timeline[Index].CycleExecuted = CurrentCycle;
64 LastCycle = std::max(LastCycle, CurrentCycle);
65}
66
67void TimelineView::onInstructionRetired(unsigned Index) {
68 if (CurrentCycle >= MaxCycle || Index >= Timeline.size())
69 return;
70 TimelineViewEntry &TVEntry = Timeline[Index];
71 TVEntry.CycleRetired = CurrentCycle;
72 LastCycle = std::max(LastCycle, CurrentCycle);
73
74 // Update the WaitTime entry which corresponds to this Index.
75
76 WaitTimeEntry &WTEntry = WaitTime[Index % AsmSequence.size()];
77 WTEntry.Executions++;
78 WTEntry.CyclesSpentInSchedulerQueue +=
79 TVEntry.CycleIssued - TVEntry.CycleDispatched;
80 assert(TVEntry.CycleDispatched <= TVEntry.CycleReady);
81 WTEntry.CyclesSpentInSQWhileReady += TVEntry.CycleIssued - TVEntry.CycleReady;
82 WTEntry.CyclesSpentAfterWBAndBeforeRetire +=
83 (TVEntry.CycleRetired - 1) - TVEntry.CycleExecuted;
84}
85
86void TimelineView::printWaitTimeEntry(raw_string_ostream &OS,
87 const WaitTimeEntry &Entry,
88 unsigned SourceIndex) const {
89 OS << SourceIndex << '.';
90 if (SourceIndex < 10)
91 OS << " ";
92 else if (SourceIndex < 100)
93 OS << " ";
94 else if (SourceIndex < 1000)
95 OS << " ";
96 else
97 OS << ' ';
98
99 if (Entry.Executions == 0) {
100 OS << " - - - - ";
101 } else {
102 double AverageTime1, AverageTime2, AverageTime3;
103 unsigned Executions = Entry.Executions;
104 AverageTime1 = (double)Entry.CyclesSpentInSchedulerQueue / Executions;
105 AverageTime2 = (double)Entry.CyclesSpentInSQWhileReady / Executions;
106 AverageTime3 = (double)Entry.CyclesSpentAfterWBAndBeforeRetire / Executions;
107 if (Executions < 10)
108 OS << ' ' << Executions << " ";
109 else if (Executions < 100)
110 OS << ' ' << Executions << " ";
111 else
112 OS << Executions << " ";
113
114 OS << format("%.1f", AverageTime1);
115 if (AverageTime1 < 10.0)
116 OS << " ";
117 else if (AverageTime1 < 100.0)
118 OS << " ";
119 else
120 OS << " ";
121
122 OS << format("%.1f", AverageTime2);
123 if (AverageTime2 < 10.0)
124 OS << " ";
125 else if (AverageTime2 < 100.0)
126 OS << " ";
127 else
128 OS << " ";
129
130 OS << format("%.1f", AverageTime3);
131 if (AverageTime3 < 10.0)
132 OS << " ";
133 else if (AverageTime3 < 100.0)
134 OS << ' ';
135 }
136}
137
138void TimelineView::printAverageWaitTimes(raw_ostream &OS) const {
139 if (WaitTime.empty())
140 return;
141
142 std::string Buffer;
143 raw_string_ostream TempStream(Buffer);
144
145 TempStream
146 << "\n\nAverage Wait times (based on the timeline view):\n"
147 << "[0]: Executions\n"
148 << "[1]: Average time spent waiting in a scheduler's queue\n"
149 << "[2]: Average time spent waiting in a scheduler's queue while ready\n"
150 << "[3]: Average time elapsed from WB until retire stage\n\n";
151 TempStream << " [0] [1] [2] [3]\n";
152
153 for (unsigned I = 0, E = WaitTime.size(); I < E; ++I) {
154 printWaitTimeEntry(TempStream, WaitTime[I], I);
155 // Append the instruction info at the end of the line.
156 const MCInst &Inst = AsmSequence.getMCInstFromIndex(I);
157 MCIP.printInst(&Inst, TempStream, "", STI);
158 TempStream << '\n';
159 TempStream.flush();
160 OS << Buffer;
161 Buffer = "";
162 }
163}
164
165void TimelineView::printTimelineViewEntry(raw_string_ostream &OS,
166 const TimelineViewEntry &Entry,
167 unsigned Iteration,
168 unsigned SourceIndex) const {
169 if (SourceIndex == 0)
170 OS << '\n';
171 OS << '[' << Iteration << ',' << SourceIndex << "]\t";
172 for (unsigned I = 0, E = Entry.CycleDispatched; I < E; ++I)
173 OS << ((I % 5 == 0) ? '.' : ' ');
174 OS << 'D';
175 if (Entry.CycleDispatched != Entry.CycleExecuted) {
176 // Zero latency instructions have the same value for CycleDispatched,
177 // CycleIssued and CycleExecuted.
178 for (unsigned I = Entry.CycleDispatched + 1, E = Entry.CycleIssued; I < E; ++I)
179 OS << '=';
180 if (Entry.CycleIssued == Entry.CycleExecuted)
181 OS << 'E';
182 else {
183 if (Entry.CycleDispatched != Entry.CycleIssued)
184 OS << 'e';
185 for (unsigned I = Entry.CycleIssued + 1, E = Entry.CycleExecuted; I < E; ++I)
186 OS << 'e';
187 OS << 'E';
188 }
189 }
190
191 for (unsigned I = Entry.CycleExecuted + 1, E = Entry.CycleRetired; I < E; ++I)
192 OS << '-';
193 OS << 'R';
194
195 // Skip other columns.
196 for (unsigned I = Entry.CycleRetired + 1, E = LastCycle; I <= E; ++I)
197 OS << ((I % 5 == 0 || I == LastCycle) ? '.' : ' ');
198}
199
200static void printTimelineHeader(raw_string_ostream &OS, unsigned Cycles) {
201 OS << "\n\nTimeline view:\n";
202 OS << " \t";
203 for (unsigned I = 0; I <= Cycles; ++I) {
204 if (((I / 10) & 1) == 0)
205 OS << ' ';
206 else
207 OS << I % 10;
208 }
209
210 OS << "\nIndex\t";
211 for (unsigned I = 0; I <= Cycles; ++I) {
212 if (((I / 10) & 1) == 0)
213 OS << I % 10;
214 else
215 OS << ' ';
216 }
217 OS << '\n';
218}
219
220void TimelineView::printTimeline(raw_ostream &OS) const {
221 std::string Buffer;
222 raw_string_ostream TempStream(Buffer);
223
224 printTimelineHeader(TempStream, LastCycle);
225 TempStream.flush();
226 OS << Buffer;
227
228 for (unsigned I = 0, E = Timeline.size(); I < E; ++I) {
229 Buffer = "";
230 const TimelineViewEntry &Entry = Timeline[I];
231 if (Entry.CycleRetired == 0)
232 return;
233
234 unsigned Iteration = I / AsmSequence.size();
235 unsigned SourceIndex = I % AsmSequence.size();
236 printTimelineViewEntry(TempStream, Entry, Iteration, SourceIndex);
237 // Append the instruction info at the end of the line.
238 const MCInst &Inst = AsmSequence.getMCInstFromIndex(I);
239 MCIP.printInst(&Inst, TempStream, "", STI);
240 TempStream << '\n';
241 TempStream.flush();
242 OS << Buffer;
243 }
244}
245
246} // namespace mca