blob: 71ebb44116d11b0d9875d1df96fca1a9c80b10a9 [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) {
Matt Davis21a8d322018-05-07 18:29:15 +000038 const unsigned Index = Event.IR.getSourceIndex();
39 if (CurrentCycle >= MaxCycle || Index >= Timeline.size())
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000040 return;
Clement Courbet844f22d2018-03-13 13:11:01 +000041 switch (Event.Type) {
42 case HWInstructionEvent::Retired: {
Matt Davis21a8d322018-05-07 18:29:15 +000043 TimelineViewEntry &TVEntry = Timeline[Index];
Clement Courbet844f22d2018-03-13 13:11:01 +000044 TVEntry.CycleRetired = CurrentCycle;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000045
Clement Courbet844f22d2018-03-13 13:11:01 +000046 // Update the WaitTime entry which corresponds to this Index.
Matt Davis21a8d322018-05-07 18:29:15 +000047 WaitTimeEntry &WTEntry = WaitTime[Index % AsmSequence.size()];
Clement Courbet844f22d2018-03-13 13:11:01 +000048 WTEntry.Executions++;
49 WTEntry.CyclesSpentInSchedulerQueue +=
50 TVEntry.CycleIssued - TVEntry.CycleDispatched;
51 assert(TVEntry.CycleDispatched <= TVEntry.CycleReady);
52 WTEntry.CyclesSpentInSQWhileReady +=
53 TVEntry.CycleIssued - TVEntry.CycleReady;
54 WTEntry.CyclesSpentAfterWBAndBeforeRetire +=
55 (TVEntry.CycleRetired - 1) - TVEntry.CycleExecuted;
56 break;
57 }
58 case HWInstructionEvent::Ready:
Matt Davis21a8d322018-05-07 18:29:15 +000059 Timeline[Index].CycleReady = CurrentCycle;
Clement Courbet844f22d2018-03-13 13:11:01 +000060 break;
61 case HWInstructionEvent::Issued:
Matt Davis21a8d322018-05-07 18:29:15 +000062 Timeline[Index].CycleIssued = CurrentCycle;
Clement Courbet844f22d2018-03-13 13:11:01 +000063 break;
64 case HWInstructionEvent::Executed:
Matt Davis21a8d322018-05-07 18:29:15 +000065 Timeline[Index].CycleExecuted = CurrentCycle;
Clement Courbet844f22d2018-03-13 13:11:01 +000066 break;
67 case HWInstructionEvent::Dispatched:
Matt Davis21a8d322018-05-07 18:29:15 +000068 Timeline[Index].CycleDispatched = CurrentCycle;
Clement Courbet844f22d2018-03-13 13:11:01 +000069 break;
70 default:
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000071 return;
Clement Courbet844f22d2018-03-13 13:11:01 +000072 }
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000073 LastCycle = std::max(LastCycle, CurrentCycle);
74}
75
Andrea Di Biagioc9f409e2018-04-10 09:55:33 +000076static void printAverageTime(raw_string_ostream &OS, double AverageTime) {
77 // Round to the nearest tenth.
78 OS << format("%.1f", floor((AverageTime * 10) + 0.5)/10);
79 if (AverageTime < 10.0)
80 OS << " ";
81 else if (AverageTime < 100.0)
82 OS << " ";
83 else
84 OS << " ";
85}
86
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000087void TimelineView::printWaitTimeEntry(raw_string_ostream &OS,
88 const WaitTimeEntry &Entry,
89 unsigned SourceIndex) const {
90 OS << SourceIndex << '.';
91 if (SourceIndex < 10)
92 OS << " ";
93 else if (SourceIndex < 100)
94 OS << " ";
95 else if (SourceIndex < 1000)
96 OS << " ";
97 else
98 OS << ' ';
99
100 if (Entry.Executions == 0) {
Andrea Di Biagioa7c3c452018-05-15 15:18:05 +0000101 OS << " - - - - ";
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000102 } else {
103 double AverageTime1, AverageTime2, AverageTime3;
104 unsigned Executions = Entry.Executions;
105 AverageTime1 = (double)Entry.CyclesSpentInSchedulerQueue / Executions;
106 AverageTime2 = (double)Entry.CyclesSpentInSQWhileReady / Executions;
107 AverageTime3 = (double)Entry.CyclesSpentAfterWBAndBeforeRetire / Executions;
108 if (Executions < 10)
109 OS << ' ' << Executions << " ";
110 else if (Executions < 100)
111 OS << ' ' << Executions << " ";
112 else
113 OS << Executions << " ";
114
Andrea Di Biagioc9f409e2018-04-10 09:55:33 +0000115 printAverageTime(OS, AverageTime1);
116 printAverageTime(OS, AverageTime2);
117 printAverageTime(OS, AverageTime3);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000118 }
119}
120
121void TimelineView::printAverageWaitTimes(raw_ostream &OS) const {
122 if (WaitTime.empty())
123 return;
124
125 std::string Buffer;
126 raw_string_ostream TempStream(Buffer);
127
128 TempStream
129 << "\n\nAverage Wait times (based on the timeline view):\n"
130 << "[0]: Executions\n"
131 << "[1]: Average time spent waiting in a scheduler's queue\n"
132 << "[2]: Average time spent waiting in a scheduler's queue while ready\n"
133 << "[3]: Average time elapsed from WB until retire stage\n\n";
134 TempStream << " [0] [1] [2] [3]\n";
135
Andrea Di Biagioa7c3c452018-05-15 15:18:05 +0000136 // Use a different string stream for the instruction.
137 std::string Instruction;
138 raw_string_ostream InstrStream(Instruction);
139
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000140 for (unsigned I = 0, E = WaitTime.size(); I < E; ++I) {
141 printWaitTimeEntry(TempStream, WaitTime[I], I);
142 // Append the instruction info at the end of the line.
143 const MCInst &Inst = AsmSequence.getMCInstFromIndex(I);
Andrea Di Biagioa7c3c452018-05-15 15:18:05 +0000144
145 MCIP.printInst(&Inst, InstrStream, "", STI);
146 InstrStream.flush();
147
148 // Consume any tabs or spaces at the beginning of the string.
149 StringRef Str(Instruction);
150 Str = Str.ltrim();
151 TempStream << " " << Str << '\n';
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000152 TempStream.flush();
Andrea Di Biagioa7c3c452018-05-15 15:18:05 +0000153 Instruction = "";
154
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000155 OS << Buffer;
156 Buffer = "";
157 }
158}
159
160void TimelineView::printTimelineViewEntry(raw_string_ostream &OS,
161 const TimelineViewEntry &Entry,
162 unsigned Iteration,
163 unsigned SourceIndex) const {
Andrea Di Biagioc9f409e2018-04-10 09:55:33 +0000164 if (Iteration == 0 && SourceIndex == 0)
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000165 OS << '\n';
166 OS << '[' << Iteration << ',' << SourceIndex << "]\t";
167 for (unsigned I = 0, E = Entry.CycleDispatched; I < E; ++I)
168 OS << ((I % 5 == 0) ? '.' : ' ');
Matt Davis35df8b242018-05-04 17:19:40 +0000169 OS << TimelineView::DisplayChar::Dispatched;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000170 if (Entry.CycleDispatched != Entry.CycleExecuted) {
171 // Zero latency instructions have the same value for CycleDispatched,
172 // CycleIssued and CycleExecuted.
Andrea Di Biagio53e6ade2018-03-09 12:50:42 +0000173 for (unsigned I = Entry.CycleDispatched + 1, E = Entry.CycleIssued; I < E;
174 ++I)
Matt Davis35df8b242018-05-04 17:19:40 +0000175 OS << TimelineView::DisplayChar::Waiting;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000176 if (Entry.CycleIssued == Entry.CycleExecuted)
Matt Davis35df8b242018-05-04 17:19:40 +0000177 OS << TimelineView::DisplayChar::DisplayChar::Executed;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000178 else {
179 if (Entry.CycleDispatched != Entry.CycleIssued)
Matt Davis35df8b242018-05-04 17:19:40 +0000180 OS << TimelineView::DisplayChar::Executing;
Andrea Di Biagio53e6ade2018-03-09 12:50:42 +0000181 for (unsigned I = Entry.CycleIssued + 1, E = Entry.CycleExecuted; I < E;
182 ++I)
Matt Davis35df8b242018-05-04 17:19:40 +0000183 OS << TimelineView::DisplayChar::Executing;
184 OS << TimelineView::DisplayChar::Executed;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000185 }
186 }
187
188 for (unsigned I = Entry.CycleExecuted + 1, E = Entry.CycleRetired; I < E; ++I)
Matt Davis35df8b242018-05-04 17:19:40 +0000189 OS << TimelineView::DisplayChar::RetireLag;
190 OS << TimelineView::DisplayChar::Retired;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000191
192 // Skip other columns.
193 for (unsigned I = Entry.CycleRetired + 1, E = LastCycle; I <= E; ++I)
194 OS << ((I % 5 == 0 || I == LastCycle) ? '.' : ' ');
195}
196
197static void printTimelineHeader(raw_string_ostream &OS, unsigned Cycles) {
198 OS << "\n\nTimeline view:\n";
199 OS << " \t";
200 for (unsigned I = 0; I <= Cycles; ++I) {
201 if (((I / 10) & 1) == 0)
202 OS << ' ';
203 else
204 OS << I % 10;
205 }
206
207 OS << "\nIndex\t";
208 for (unsigned I = 0; I <= Cycles; ++I) {
209 if (((I / 10) & 1) == 0)
210 OS << I % 10;
211 else
212 OS << ' ';
213 }
214 OS << '\n';
215}
216
217void TimelineView::printTimeline(raw_ostream &OS) const {
218 std::string Buffer;
219 raw_string_ostream TempStream(Buffer);
220
221 printTimelineHeader(TempStream, LastCycle);
222 TempStream.flush();
223 OS << Buffer;
224
Andrea Di Biagioa7c3c452018-05-15 15:18:05 +0000225 // Use a different string stream for the instruction.
226 std::string Instruction;
227 raw_string_ostream InstrStream(Instruction);
228
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000229 for (unsigned I = 0, E = Timeline.size(); I < E; ++I) {
230 Buffer = "";
231 const TimelineViewEntry &Entry = Timeline[I];
232 if (Entry.CycleRetired == 0)
233 return;
234
235 unsigned Iteration = I / AsmSequence.size();
236 unsigned SourceIndex = I % AsmSequence.size();
237 printTimelineViewEntry(TempStream, Entry, Iteration, SourceIndex);
238 // Append the instruction info at the end of the line.
239 const MCInst &Inst = AsmSequence.getMCInstFromIndex(I);
Andrea Di Biagioa7c3c452018-05-15 15:18:05 +0000240 MCIP.printInst(&Inst, InstrStream, "", STI);
241 InstrStream.flush();
242
243 // Consume any tabs or spaces at the beginning of the string.
244 StringRef Str(Instruction);
245 Str = Str.ltrim();
246 TempStream << " " << Str << '\n';
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000247 TempStream.flush();
Andrea Di Biagioa7c3c452018-05-15 15:18:05 +0000248 Instruction = "";
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000249 OS << Buffer;
250 }
251}
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000252} // namespace mca