xref: /freebsd-src/contrib/llvm-project/llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
10b57cec5SDimitry Andric //===--------------------- RetireControlUnitStatistics.cpp ------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric /// \file
90b57cec5SDimitry Andric ///
100b57cec5SDimitry Andric /// This file implements the RetireControlUnitStatistics interface.
110b57cec5SDimitry Andric ///
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "Views/RetireControlUnitStatistics.h"
150b57cec5SDimitry Andric #include "llvm/Support/Format.h"
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric namespace llvm {
180b57cec5SDimitry Andric namespace mca {
190b57cec5SDimitry Andric 
RetireControlUnitStatistics(const MCSchedModel & SM)200b57cec5SDimitry Andric RetireControlUnitStatistics::RetireControlUnitStatistics(const MCSchedModel &SM)
210b57cec5SDimitry Andric     : NumRetired(0), NumCycles(0), EntriesInUse(0), MaxUsedEntries(0),
220b57cec5SDimitry Andric       SumOfUsedEntries(0) {
230b57cec5SDimitry Andric   TotalROBEntries = SM.MicroOpBufferSize;
240b57cec5SDimitry Andric   if (SM.hasExtraProcessorInfo()) {
250b57cec5SDimitry Andric     const MCExtraProcessorInfo &EPI = SM.getExtraProcessorInfo();
260b57cec5SDimitry Andric     if (EPI.ReorderBufferSize)
270b57cec5SDimitry Andric       TotalROBEntries = EPI.ReorderBufferSize;
280b57cec5SDimitry Andric   }
290b57cec5SDimitry Andric }
300b57cec5SDimitry Andric 
onEvent(const HWInstructionEvent & Event)310b57cec5SDimitry Andric void RetireControlUnitStatistics::onEvent(const HWInstructionEvent &Event) {
320b57cec5SDimitry Andric   if (Event.Type == HWInstructionEvent::Dispatched) {
330b57cec5SDimitry Andric     unsigned NumEntries =
340b57cec5SDimitry Andric         static_cast<const HWInstructionDispatchedEvent &>(Event).MicroOpcodes;
350b57cec5SDimitry Andric     EntriesInUse += NumEntries;
360b57cec5SDimitry Andric   }
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric   if (Event.Type == HWInstructionEvent::Retired) {
390b57cec5SDimitry Andric     unsigned ReleasedEntries = Event.IR.getInstruction()->getDesc().NumMicroOps;
400b57cec5SDimitry Andric     assert(EntriesInUse >= ReleasedEntries && "Invalid internal state!");
410b57cec5SDimitry Andric     EntriesInUse -= ReleasedEntries;
420b57cec5SDimitry Andric     ++NumRetired;
430b57cec5SDimitry Andric   }
440b57cec5SDimitry Andric }
450b57cec5SDimitry Andric 
onCycleEnd()460b57cec5SDimitry Andric void RetireControlUnitStatistics::onCycleEnd() {
470b57cec5SDimitry Andric   // Update histogram
480b57cec5SDimitry Andric   RetiredPerCycle[NumRetired]++;
490b57cec5SDimitry Andric   NumRetired = 0;
500b57cec5SDimitry Andric   ++NumCycles;
510b57cec5SDimitry Andric   MaxUsedEntries = std::max(MaxUsedEntries, EntriesInUse);
520b57cec5SDimitry Andric   SumOfUsedEntries += EntriesInUse;
530b57cec5SDimitry Andric }
540b57cec5SDimitry Andric 
printView(raw_ostream & OS) const550b57cec5SDimitry Andric void RetireControlUnitStatistics::printView(raw_ostream &OS) const {
560b57cec5SDimitry Andric   std::string Buffer;
570b57cec5SDimitry Andric   raw_string_ostream TempStream(Buffer);
580b57cec5SDimitry Andric   TempStream << "\n\nRetire Control Unit - "
590b57cec5SDimitry Andric              << "number of cycles where we saw N instructions retired:\n";
600b57cec5SDimitry Andric   TempStream << "[# retired], [# cycles]\n";
610b57cec5SDimitry Andric 
62480093f4SDimitry Andric   for (const std::pair<const unsigned, unsigned> &Entry : RetiredPerCycle) {
630b57cec5SDimitry Andric     TempStream << " " << Entry.first;
640b57cec5SDimitry Andric     if (Entry.first < 10)
650b57cec5SDimitry Andric       TempStream << ",           ";
660b57cec5SDimitry Andric     else
670b57cec5SDimitry Andric       TempStream << ",          ";
680b57cec5SDimitry Andric     TempStream << Entry.second << "  ("
690b57cec5SDimitry Andric                << format("%.1f", ((double)Entry.second / NumCycles) * 100.0)
700b57cec5SDimitry Andric                << "%)\n";
710b57cec5SDimitry Andric   }
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   unsigned AvgUsage = (double)SumOfUsedEntries / NumCycles;
74*fe6060f1SDimitry Andric   double MaxUsagePercentage =
75*fe6060f1SDimitry Andric       ((double)MaxUsedEntries / TotalROBEntries) * 100.0;
760b57cec5SDimitry Andric   double NormalizedMaxPercentage = floor((MaxUsagePercentage * 10) + 0.5) / 10;
770b57cec5SDimitry Andric   double AvgUsagePercentage = ((double)AvgUsage / TotalROBEntries) * 100.0;
780b57cec5SDimitry Andric   double NormalizedAvgPercentage = floor((AvgUsagePercentage * 10) + 0.5) / 10;
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   TempStream << "\nTotal ROB Entries:                " << TotalROBEntries
810b57cec5SDimitry Andric              << "\nMax Used ROB Entries:             " << MaxUsedEntries
820b57cec5SDimitry Andric              << format("  ( %.1f%% )", NormalizedMaxPercentage)
830b57cec5SDimitry Andric              << "\nAverage Used ROB Entries per cy:  " << AvgUsage
840b57cec5SDimitry Andric              << format("  ( %.1f%% )\n", NormalizedAvgPercentage);
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   TempStream.flush();
870b57cec5SDimitry Andric   OS << Buffer;
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric } // namespace mca
910b57cec5SDimitry Andric } // namespace llvm
92