blob: 01fb84e79abef744f0f600892f708ffa9b675d54 [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 Biagioc9f409e2018-04-10 09:55:33 +000075static void printAverageTime(raw_string_ostream &OS, double AverageTime) {
76 // Round to the nearest tenth.
77 OS << format("%.1f", floor((AverageTime * 10) + 0.5)/10);
78 if (AverageTime < 10.0)
79 OS << " ";
80 else if (AverageTime < 100.0)
81 OS << " ";
82 else
83 OS << " ";
84}
85
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000086void 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
Andrea Di Biagioc9f409e2018-04-10 09:55:33 +0000114 printAverageTime(OS, AverageTime1);
115 printAverageTime(OS, AverageTime2);
116 printAverageTime(OS, AverageTime3);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000117 }
118}
119
120void TimelineView::printAverageWaitTimes(raw_ostream &OS) const {
121 if (WaitTime.empty())
122 return;
123
124 std::string Buffer;
125 raw_string_ostream TempStream(Buffer);
126
127 TempStream
128 << "\n\nAverage Wait times (based on the timeline view):\n"
129 << "[0]: Executions\n"
130 << "[1]: Average time spent waiting in a scheduler's queue\n"
131 << "[2]: Average time spent waiting in a scheduler's queue while ready\n"
132 << "[3]: Average time elapsed from WB until retire stage\n\n";
133 TempStream << " [0] [1] [2] [3]\n";
134
135 for (unsigned I = 0, E = WaitTime.size(); I < E; ++I) {
136 printWaitTimeEntry(TempStream, WaitTime[I], I);
137 // Append the instruction info at the end of the line.
138 const MCInst &Inst = AsmSequence.getMCInstFromIndex(I);
139 MCIP.printInst(&Inst, TempStream, "", STI);
140 TempStream << '\n';
141 TempStream.flush();
142 OS << Buffer;
143 Buffer = "";
144 }
145}
146
147void TimelineView::printTimelineViewEntry(raw_string_ostream &OS,
148 const TimelineViewEntry &Entry,
149 unsigned Iteration,
150 unsigned SourceIndex) const {
Andrea Di Biagioc9f409e2018-04-10 09:55:33 +0000151 if (Iteration == 0 && SourceIndex == 0)
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000152 OS << '\n';
153 OS << '[' << Iteration << ',' << SourceIndex << "]\t";
154 for (unsigned I = 0, E = Entry.CycleDispatched; I < E; ++I)
155 OS << ((I % 5 == 0) ? '.' : ' ');
Matt Davis35df8b242018-05-04 17:19:40 +0000156 OS << TimelineView::DisplayChar::Dispatched;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000157 if (Entry.CycleDispatched != Entry.CycleExecuted) {
158 // Zero latency instructions have the same value for CycleDispatched,
159 // CycleIssued and CycleExecuted.
Andrea Di Biagio53e6ade2018-03-09 12:50:42 +0000160 for (unsigned I = Entry.CycleDispatched + 1, E = Entry.CycleIssued; I < E;
161 ++I)
Matt Davis35df8b242018-05-04 17:19:40 +0000162 OS << TimelineView::DisplayChar::Waiting;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000163 if (Entry.CycleIssued == Entry.CycleExecuted)
Matt Davis35df8b242018-05-04 17:19:40 +0000164 OS << TimelineView::DisplayChar::DisplayChar::Executed;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000165 else {
166 if (Entry.CycleDispatched != Entry.CycleIssued)
Matt Davis35df8b242018-05-04 17:19:40 +0000167 OS << TimelineView::DisplayChar::Executing;
Andrea Di Biagio53e6ade2018-03-09 12:50:42 +0000168 for (unsigned I = Entry.CycleIssued + 1, E = Entry.CycleExecuted; I < E;
169 ++I)
Matt Davis35df8b242018-05-04 17:19:40 +0000170 OS << TimelineView::DisplayChar::Executing;
171 OS << TimelineView::DisplayChar::Executed;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000172 }
173 }
174
175 for (unsigned I = Entry.CycleExecuted + 1, E = Entry.CycleRetired; I < E; ++I)
Matt Davis35df8b242018-05-04 17:19:40 +0000176 OS << TimelineView::DisplayChar::RetireLag;
177 OS << TimelineView::DisplayChar::Retired;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000178
179 // Skip other columns.
180 for (unsigned I = Entry.CycleRetired + 1, E = LastCycle; I <= E; ++I)
181 OS << ((I % 5 == 0 || I == LastCycle) ? '.' : ' ');
182}
183
184static void printTimelineHeader(raw_string_ostream &OS, unsigned Cycles) {
185 OS << "\n\nTimeline view:\n";
186 OS << " \t";
187 for (unsigned I = 0; I <= Cycles; ++I) {
188 if (((I / 10) & 1) == 0)
189 OS << ' ';
190 else
191 OS << I % 10;
192 }
193
194 OS << "\nIndex\t";
195 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;
206 raw_string_ostream TempStream(Buffer);
207
208 printTimelineHeader(TempStream, LastCycle);
209 TempStream.flush();
210 OS << Buffer;
211
212 for (unsigned I = 0, E = Timeline.size(); I < E; ++I) {
213 Buffer = "";
214 const TimelineViewEntry &Entry = Timeline[I];
215 if (Entry.CycleRetired == 0)
216 return;
217
218 unsigned Iteration = I / AsmSequence.size();
219 unsigned SourceIndex = I % AsmSequence.size();
220 printTimelineViewEntry(TempStream, Entry, Iteration, SourceIndex);
221 // Append the instruction info at the end of the line.
222 const MCInst &Inst = AsmSequence.getMCInstFromIndex(I);
223 MCIP.printInst(&Inst, TempStream, "", STI);
224 TempStream << '\n';
225 TempStream.flush();
226 OS << Buffer;
227 }
228}
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000229} // namespace mca