1*0b57cec5SDimitry Andric //===--------------------- RetireControlUnitStatistics.cpp ------*- C++ -*-===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric /// \file
9*0b57cec5SDimitry Andric ///
10*0b57cec5SDimitry Andric /// This file implements the RetireControlUnitStatistics interface.
11*0b57cec5SDimitry Andric ///
12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
13*0b57cec5SDimitry Andric
14*0b57cec5SDimitry Andric #include "Views/RetireControlUnitStatistics.h"
15*0b57cec5SDimitry Andric #include "llvm/Support/Format.h"
16*0b57cec5SDimitry Andric
17*0b57cec5SDimitry Andric namespace llvm {
18*0b57cec5SDimitry Andric namespace mca {
19*0b57cec5SDimitry Andric
RetireControlUnitStatistics(const MCSchedModel & SM)20*0b57cec5SDimitry Andric RetireControlUnitStatistics::RetireControlUnitStatistics(const MCSchedModel &SM)
21*0b57cec5SDimitry Andric : NumRetired(0), NumCycles(0), EntriesInUse(0), MaxUsedEntries(0),
22*0b57cec5SDimitry Andric SumOfUsedEntries(0) {
23*0b57cec5SDimitry Andric TotalROBEntries = SM.MicroOpBufferSize;
24*0b57cec5SDimitry Andric if (SM.hasExtraProcessorInfo()) {
25*0b57cec5SDimitry Andric const MCExtraProcessorInfo &EPI = SM.getExtraProcessorInfo();
26*0b57cec5SDimitry Andric if (EPI.ReorderBufferSize)
27*0b57cec5SDimitry Andric TotalROBEntries = EPI.ReorderBufferSize;
28*0b57cec5SDimitry Andric }
29*0b57cec5SDimitry Andric }
30*0b57cec5SDimitry Andric
onEvent(const HWInstructionEvent & Event)31*0b57cec5SDimitry Andric void RetireControlUnitStatistics::onEvent(const HWInstructionEvent &Event) {
32*0b57cec5SDimitry Andric if (Event.Type == HWInstructionEvent::Dispatched) {
33*0b57cec5SDimitry Andric unsigned NumEntries =
34*0b57cec5SDimitry Andric static_cast<const HWInstructionDispatchedEvent &>(Event).MicroOpcodes;
35*0b57cec5SDimitry Andric EntriesInUse += NumEntries;
36*0b57cec5SDimitry Andric }
37*0b57cec5SDimitry Andric
38*0b57cec5SDimitry Andric if (Event.Type == HWInstructionEvent::Retired) {
39*0b57cec5SDimitry Andric unsigned ReleasedEntries = Event.IR.getInstruction()->getDesc().NumMicroOps;
40*0b57cec5SDimitry Andric assert(EntriesInUse >= ReleasedEntries && "Invalid internal state!");
41*0b57cec5SDimitry Andric EntriesInUse -= ReleasedEntries;
42*0b57cec5SDimitry Andric ++NumRetired;
43*0b57cec5SDimitry Andric }
44*0b57cec5SDimitry Andric }
45*0b57cec5SDimitry Andric
onCycleEnd()46*0b57cec5SDimitry Andric void RetireControlUnitStatistics::onCycleEnd() {
47*0b57cec5SDimitry Andric // Update histogram
48*0b57cec5SDimitry Andric RetiredPerCycle[NumRetired]++;
49*0b57cec5SDimitry Andric NumRetired = 0;
50*0b57cec5SDimitry Andric ++NumCycles;
51*0b57cec5SDimitry Andric MaxUsedEntries = std::max(MaxUsedEntries, EntriesInUse);
52*0b57cec5SDimitry Andric SumOfUsedEntries += EntriesInUse;
53*0b57cec5SDimitry Andric }
54*0b57cec5SDimitry Andric
printView(raw_ostream & OS) const55*0b57cec5SDimitry Andric void RetireControlUnitStatistics::printView(raw_ostream &OS) const {
56*0b57cec5SDimitry Andric std::string Buffer;
57*0b57cec5SDimitry Andric raw_string_ostream TempStream(Buffer);
58*0b57cec5SDimitry Andric TempStream << "\n\nRetire Control Unit - "
59*0b57cec5SDimitry Andric << "number of cycles where we saw N instructions retired:\n";
60*0b57cec5SDimitry Andric TempStream << "[# retired], [# cycles]\n";
61*0b57cec5SDimitry Andric
62*0b57cec5SDimitry Andric for (const std::pair<const unsigned, unsigned> &Entry : RetiredPerCycle) {
63*0b57cec5SDimitry Andric TempStream << " " << Entry.first;
64*0b57cec5SDimitry Andric if (Entry.first < 10)
65*0b57cec5SDimitry Andric TempStream << ", ";
66*0b57cec5SDimitry Andric else
67*0b57cec5SDimitry Andric TempStream << ", ";
68*0b57cec5SDimitry Andric TempStream << Entry.second << " ("
69*0b57cec5SDimitry Andric << format("%.1f", ((double)Entry.second / NumCycles) * 100.0)
70*0b57cec5SDimitry Andric << "%)\n";
71*0b57cec5SDimitry Andric }
72*0b57cec5SDimitry Andric
73*0b57cec5SDimitry Andric unsigned AvgUsage = (double)SumOfUsedEntries / NumCycles;
74*0b57cec5SDimitry Andric double MaxUsagePercentage =
75*0b57cec5SDimitry Andric ((double)MaxUsedEntries / TotalROBEntries) * 100.0;
76*0b57cec5SDimitry Andric double NormalizedMaxPercentage = floor((MaxUsagePercentage * 10) + 0.5) / 10;
77*0b57cec5SDimitry Andric double AvgUsagePercentage = ((double)AvgUsage / TotalROBEntries) * 100.0;
78*0b57cec5SDimitry Andric double NormalizedAvgPercentage = floor((AvgUsagePercentage * 10) + 0.5) / 10;
79*0b57cec5SDimitry Andric
80*0b57cec5SDimitry Andric TempStream << "\nTotal ROB Entries: " << TotalROBEntries
81*0b57cec5SDimitry Andric << "\nMax Used ROB Entries: " << MaxUsedEntries
82*0b57cec5SDimitry Andric << format(" ( %.1f%% )", NormalizedMaxPercentage)
83*0b57cec5SDimitry Andric << "\nAverage Used ROB Entries per cy: " << AvgUsage
84*0b57cec5SDimitry Andric << format(" ( %.1f%% )\n", NormalizedAvgPercentage);
85*0b57cec5SDimitry Andric
86*0b57cec5SDimitry Andric TempStream.flush();
87*0b57cec5SDimitry Andric OS << Buffer;
88*0b57cec5SDimitry Andric }
89*0b57cec5SDimitry Andric
90*0b57cec5SDimitry Andric } // namespace mca
91 } // namespace llvm
92