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