blob: 79dfa3a9d80ca19a03ecd9dc53ca40c4d4c68960 [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
Matt Davis10aa09f2018-08-24 20:24:53 +000015#include "Views/TimelineView.h"
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000016
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
Matt Davis0906a7f2018-07-12 16:56:17 +000037void TimelineView::onEvent(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 Biagio039349a2018-05-15 18:11:45 +000076void TimelineView::printWaitTimeEntry(formatted_raw_ostream &OS,
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000077 const WaitTimeEntry &Entry,
78 unsigned SourceIndex) const {
79 OS << SourceIndex << '.';
Andrea Di Biagio039349a2018-05-15 18:11:45 +000080 OS.PadToColumn(7);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000081
82 if (Entry.Executions == 0) {
Andrea Di Biagio039349a2018-05-15 18:11:45 +000083 OS << "- - - - ";
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000084 } else {
85 double AverageTime1, AverageTime2, AverageTime3;
86 unsigned Executions = Entry.Executions;
87 AverageTime1 = (double)Entry.CyclesSpentInSchedulerQueue / Executions;
88 AverageTime2 = (double)Entry.CyclesSpentInSQWhileReady / Executions;
89 AverageTime3 = (double)Entry.CyclesSpentAfterWBAndBeforeRetire / Executions;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000090
Andrea Di Biagio039349a2018-05-15 18:11:45 +000091 OS << Executions;
92 OS.PadToColumn(13);
93
94 OS << format("%.1f", floor((AverageTime1 * 10) + 0.5) / 10);
95 OS.PadToColumn(20);
96 OS << format("%.1f", floor((AverageTime2 * 10) + 0.5) / 10);
97 OS.PadToColumn(27);
98 OS << format("%.1f", floor((AverageTime3 * 10) + 0.5) / 10);
99 OS.PadToColumn(34);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000100 }
101}
102
103void TimelineView::printAverageWaitTimes(raw_ostream &OS) const {
104 if (WaitTime.empty())
105 return;
106
107 std::string Buffer;
108 raw_string_ostream TempStream(Buffer);
Andrea Di Biagio039349a2018-05-15 18:11:45 +0000109 formatted_raw_ostream FOS(TempStream);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000110
Andrea Di Biagio039349a2018-05-15 18:11:45 +0000111 FOS << "\n\nAverage Wait times (based on the timeline view):\n"
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000112 << "[0]: Executions\n"
113 << "[1]: Average time spent waiting in a scheduler's queue\n"
114 << "[2]: Average time spent waiting in a scheduler's queue while ready\n"
115 << "[3]: Average time elapsed from WB until retire stage\n\n";
Andrea Di Biagio039349a2018-05-15 18:11:45 +0000116 FOS << " [0] [1] [2] [3]\n";
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000117
Andrea Di Biagioa7c3c452018-05-15 15:18:05 +0000118 // Use a different string stream for the instruction.
119 std::string Instruction;
120 raw_string_ostream InstrStream(Instruction);
121
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000122 for (unsigned I = 0, E = WaitTime.size(); I < E; ++I) {
Andrea Di Biagio039349a2018-05-15 18:11:45 +0000123 printWaitTimeEntry(FOS, WaitTime[I], I);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000124 // Append the instruction info at the end of the line.
125 const MCInst &Inst = AsmSequence.getMCInstFromIndex(I);
Andrea Di Biagioa7c3c452018-05-15 15:18:05 +0000126
127 MCIP.printInst(&Inst, InstrStream, "", STI);
128 InstrStream.flush();
129
130 // Consume any tabs or spaces at the beginning of the string.
131 StringRef Str(Instruction);
132 Str = Str.ltrim();
Andrea Di Biagio039349a2018-05-15 18:11:45 +0000133 FOS << " " << Str << '\n';
134 FOS.flush();
Andrea Di Biagioa7c3c452018-05-15 15:18:05 +0000135 Instruction = "";
136
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000137 OS << Buffer;
138 Buffer = "";
139 }
140}
141
Andrea Di Biagio039349a2018-05-15 18:11:45 +0000142void TimelineView::printTimelineViewEntry(formatted_raw_ostream &OS,
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000143 const TimelineViewEntry &Entry,
144 unsigned Iteration,
145 unsigned SourceIndex) const {
Andrea Di Biagioc9f409e2018-04-10 09:55:33 +0000146 if (Iteration == 0 && SourceIndex == 0)
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000147 OS << '\n';
Andrea Di Biagio039349a2018-05-15 18:11:45 +0000148 OS << '[' << Iteration << ',' << SourceIndex << ']';
149 OS.PadToColumn(10);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000150 for (unsigned I = 0, E = Entry.CycleDispatched; I < E; ++I)
151 OS << ((I % 5 == 0) ? '.' : ' ');
Matt Davis35df8b242018-05-04 17:19:40 +0000152 OS << TimelineView::DisplayChar::Dispatched;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000153 if (Entry.CycleDispatched != Entry.CycleExecuted) {
154 // Zero latency instructions have the same value for CycleDispatched,
155 // CycleIssued and CycleExecuted.
Andrea Di Biagio53e6ade2018-03-09 12:50:42 +0000156 for (unsigned I = Entry.CycleDispatched + 1, E = Entry.CycleIssued; I < E;
157 ++I)
Matt Davis35df8b242018-05-04 17:19:40 +0000158 OS << TimelineView::DisplayChar::Waiting;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000159 if (Entry.CycleIssued == Entry.CycleExecuted)
Matt Davis35df8b242018-05-04 17:19:40 +0000160 OS << TimelineView::DisplayChar::DisplayChar::Executed;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000161 else {
162 if (Entry.CycleDispatched != Entry.CycleIssued)
Matt Davis35df8b242018-05-04 17:19:40 +0000163 OS << TimelineView::DisplayChar::Executing;
Andrea Di Biagio53e6ade2018-03-09 12:50:42 +0000164 for (unsigned I = Entry.CycleIssued + 1, E = Entry.CycleExecuted; I < E;
165 ++I)
Matt Davis35df8b242018-05-04 17:19:40 +0000166 OS << TimelineView::DisplayChar::Executing;
167 OS << TimelineView::DisplayChar::Executed;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000168 }
169 }
170
171 for (unsigned I = Entry.CycleExecuted + 1, E = Entry.CycleRetired; I < E; ++I)
Matt Davis35df8b242018-05-04 17:19:40 +0000172 OS << TimelineView::DisplayChar::RetireLag;
173 OS << TimelineView::DisplayChar::Retired;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000174
175 // Skip other columns.
176 for (unsigned I = Entry.CycleRetired + 1, E = LastCycle; I <= E; ++I)
177 OS << ((I % 5 == 0 || I == LastCycle) ? '.' : ' ');
178}
179
Andrea Di Biagio039349a2018-05-15 18:11:45 +0000180static void printTimelineHeader(formatted_raw_ostream &OS, unsigned Cycles) {
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000181 OS << "\n\nTimeline view:\n";
Andrea Di Biagiocb1ed402018-05-21 17:11:56 +0000182 if (Cycles >= 10) {
183 OS.PadToColumn(10);
184 for (unsigned I = 0; I <= Cycles; ++I) {
185 if (((I / 10) & 1) == 0)
186 OS << ' ';
187 else
188 OS << I % 10;
189 }
190 OS << '\n';
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000191 }
192
Andrea Di Biagiocb1ed402018-05-21 17:11:56 +0000193 OS << "Index";
Andrea Di Biagio039349a2018-05-15 18:11:45 +0000194 OS.PadToColumn(10);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000195 for (unsigned I = 0; I <= Cycles; ++I) {
196 if (((I / 10) & 1) == 0)
197 OS << I % 10;
198 else
199 OS << ' ';
200 }
201 OS << '\n';
202}
203
204void TimelineView::printTimeline(raw_ostream &OS) const {
205 std::string Buffer;
Andrea Di Biagio039349a2018-05-15 18:11:45 +0000206 raw_string_ostream StringStream(Buffer);
207 formatted_raw_ostream FOS(StringStream);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000208
Andrea Di Biagio039349a2018-05-15 18:11:45 +0000209 printTimelineHeader(FOS, LastCycle);
210 FOS.flush();
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000211 OS << Buffer;
212
Andrea Di Biagioa7c3c452018-05-15 15:18:05 +0000213 // Use a different string stream for the instruction.
214 std::string Instruction;
215 raw_string_ostream InstrStream(Instruction);
216
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000217 for (unsigned I = 0, E = Timeline.size(); I < E; ++I) {
218 Buffer = "";
219 const TimelineViewEntry &Entry = Timeline[I];
220 if (Entry.CycleRetired == 0)
221 return;
222
223 unsigned Iteration = I / AsmSequence.size();
224 unsigned SourceIndex = I % AsmSequence.size();
Andrea Di Biagio039349a2018-05-15 18:11:45 +0000225 printTimelineViewEntry(FOS, Entry, Iteration, SourceIndex);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000226 // Append the instruction info at the end of the line.
227 const MCInst &Inst = AsmSequence.getMCInstFromIndex(I);
Andrea Di Biagioa7c3c452018-05-15 15:18:05 +0000228 MCIP.printInst(&Inst, InstrStream, "", STI);
229 InstrStream.flush();
230
231 // Consume any tabs or spaces at the beginning of the string.
232 StringRef Str(Instruction);
233 Str = Str.ltrim();
Andrea Di Biagio039349a2018-05-15 18:11:45 +0000234 FOS << " " << Str << '\n';
235 FOS.flush();
Andrea Di Biagioa7c3c452018-05-15 15:18:05 +0000236 Instruction = "";
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000237 OS << Buffer;
238 }
239}
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000240} // namespace mca