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