xref: /llvm-project/llvm/lib/MCA/HardwareUnits/RetireControlUnit.cpp (revision 292da93d59a3688ffc95c10de7986472242e8f1d)
1cc5e6a72SClement Courbet //===---------------------- RetireControlUnit.cpp ---------------*- C++ -*-===//
2cc5e6a72SClement Courbet //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6cc5e6a72SClement Courbet //
7cc5e6a72SClement Courbet //===----------------------------------------------------------------------===//
8cc5e6a72SClement Courbet /// \file
9cc5e6a72SClement Courbet ///
10cc5e6a72SClement Courbet /// This file simulates the hardware responsible for retiring instructions.
11cc5e6a72SClement Courbet ///
12cc5e6a72SClement Courbet //===----------------------------------------------------------------------===//
13cc5e6a72SClement Courbet 
14cc5e6a72SClement Courbet #include "llvm/MCA/HardwareUnits/RetireControlUnit.h"
15cc5e6a72SClement Courbet #include "llvm/Support/Debug.h"
16cc5e6a72SClement Courbet 
17cc5e6a72SClement Courbet #define DEBUG_TYPE "llvm-mca"
18cc5e6a72SClement Courbet 
19cc5e6a72SClement Courbet namespace llvm {
20cc5e6a72SClement Courbet namespace mca {
21cc5e6a72SClement Courbet 
RetireControlUnit(const MCSchedModel & SM)22cc5e6a72SClement Courbet RetireControlUnit::RetireControlUnit(const MCSchedModel &SM)
23cc5e6a72SClement Courbet     : NextAvailableSlotIdx(0), CurrentInstructionSlotIdx(0),
247340fd68SJay Foad       AvailableEntries(SM.isOutOfOrder() ? SM.MicroOpBufferSize : 0),
257340fd68SJay Foad       MaxRetirePerCycle(0) {
26*292da93dSAndrew Savonichev   assert(SM.isOutOfOrder() &&
27*292da93dSAndrew Savonichev          "RetireControlUnit is not available for in-order processors");
28cc5e6a72SClement Courbet   // Check if the scheduling model provides extra information about the machine
29cc5e6a72SClement Courbet   // processor. If so, then use that information to set the reorder buffer size
30cc5e6a72SClement Courbet   // and the maximum number of instructions retired per cycle.
31cc5e6a72SClement Courbet   if (SM.hasExtraProcessorInfo()) {
32cc5e6a72SClement Courbet     const MCExtraProcessorInfo &EPI = SM.getExtraProcessorInfo();
33cc5e6a72SClement Courbet     if (EPI.ReorderBufferSize)
343de2f033SAndrea Di Biagio       AvailableEntries = EPI.ReorderBufferSize;
35cc5e6a72SClement Courbet     MaxRetirePerCycle = EPI.MaxRetirePerCycle;
36cc5e6a72SClement Courbet   }
373de2f033SAndrea Di Biagio   NumROBEntries = AvailableEntries;
383de2f033SAndrea Di Biagio   assert(NumROBEntries && "Invalid reorder buffer size!");
393de2f033SAndrea Di Biagio   Queue.resize(2 * NumROBEntries);
40cc5e6a72SClement Courbet }
41cc5e6a72SClement Courbet 
42cc5e6a72SClement Courbet // Reserves a number of slots, and returns a new token.
dispatch(const InstRef & IR)433de2f033SAndrea Di Biagio unsigned RetireControlUnit::dispatch(const InstRef &IR) {
443de2f033SAndrea Di Biagio   const Instruction &Inst = *IR.getInstruction();
453de2f033SAndrea Di Biagio   unsigned Entries = normalizeQuantity(Inst.getNumMicroOps());
463de2f033SAndrea Di Biagio   assert((AvailableEntries >= Entries) && "Reorder Buffer unavailable!");
473de2f033SAndrea Di Biagio 
48cc5e6a72SClement Courbet   unsigned TokenID = NextAvailableSlotIdx;
493de2f033SAndrea Di Biagio   Queue[NextAvailableSlotIdx] = {IR, Entries, false};
503de2f033SAndrea Di Biagio   NextAvailableSlotIdx += std::max(1U, Entries);
51cc5e6a72SClement Courbet   NextAvailableSlotIdx %= Queue.size();
52d791695cSAndrew Savonichev   assert(TokenID < UnhandledTokenID && "Invalid token ID");
533de2f033SAndrea Di Biagio 
543de2f033SAndrea Di Biagio   AvailableEntries -= Entries;
55cc5e6a72SClement Courbet   return TokenID;
56cc5e6a72SClement Courbet }
57cc5e6a72SClement Courbet 
getCurrentToken() const583de2f033SAndrea Di Biagio const RetireControlUnit::RUToken &RetireControlUnit::getCurrentToken() const {
593de2f033SAndrea Di Biagio   const RetireControlUnit::RUToken &Current = Queue[CurrentInstructionSlotIdx];
603de2f033SAndrea Di Biagio #ifndef NDEBUG
613de2f033SAndrea Di Biagio   const Instruction *Inst = Current.IR.getInstruction();
623de2f033SAndrea Di Biagio   assert(Inst && "Invalid RUToken in the RCU queue.");
633de2f033SAndrea Di Biagio #endif
643de2f033SAndrea Di Biagio   return Current;
653de2f033SAndrea Di Biagio }
663de2f033SAndrea Di Biagio 
computeNextSlotIdx() const673de2f033SAndrea Di Biagio unsigned RetireControlUnit::computeNextSlotIdx() const {
683de2f033SAndrea Di Biagio   const RetireControlUnit::RUToken &Current = getCurrentToken();
693de2f033SAndrea Di Biagio   unsigned NextSlotIdx = CurrentInstructionSlotIdx + std::max(1U, Current.NumSlots);
703de2f033SAndrea Di Biagio   return NextSlotIdx % Queue.size();
713de2f033SAndrea Di Biagio }
723de2f033SAndrea Di Biagio 
peekNextToken() const733de2f033SAndrea Di Biagio const RetireControlUnit::RUToken &RetireControlUnit::peekNextToken() const {
743de2f033SAndrea Di Biagio   return Queue[computeNextSlotIdx()];
75cc5e6a72SClement Courbet }
76cc5e6a72SClement Courbet 
consumeCurrentToken()77cc5e6a72SClement Courbet void RetireControlUnit::consumeCurrentToken() {
78cc5e6a72SClement Courbet   RetireControlUnit::RUToken &Current = Queue[CurrentInstructionSlotIdx];
79cc5e6a72SClement Courbet   Current.IR.getInstruction()->retire();
80cc5e6a72SClement Courbet 
81cc5e6a72SClement Courbet   // Update the slot index to be the next item in the circular queue.
823de2f033SAndrea Di Biagio   CurrentInstructionSlotIdx += std::max(1U, Current.NumSlots);
83cc5e6a72SClement Courbet   CurrentInstructionSlotIdx %= Queue.size();
843de2f033SAndrea Di Biagio   AvailableEntries += Current.NumSlots;
853de2f033SAndrea Di Biagio   Current = { InstRef(), 0U, false };
86cc5e6a72SClement Courbet }
87cc5e6a72SClement Courbet 
onInstructionExecuted(unsigned TokenID)88cc5e6a72SClement Courbet void RetireControlUnit::onInstructionExecuted(unsigned TokenID) {
89cc5e6a72SClement Courbet   assert(Queue.size() > TokenID);
903de2f033SAndrea Di Biagio   assert(Queue[TokenID].IR.getInstruction() && "Instruction was not dispatched!");
913de2f033SAndrea Di Biagio   assert(Queue[TokenID].Executed == false && "Instruction already executed!");
92cc5e6a72SClement Courbet   Queue[TokenID].Executed = true;
93cc5e6a72SClement Courbet }
94cc5e6a72SClement Courbet 
95cc5e6a72SClement Courbet #ifndef NDEBUG
dump() const96cc5e6a72SClement Courbet void RetireControlUnit::dump() const {
973de2f033SAndrea Di Biagio   dbgs() << "Retire Unit: { Total ROB Entries =" << NumROBEntries
983de2f033SAndrea Di Biagio          << ", Available ROB entries=" << AvailableEntries << " }\n";
99cc5e6a72SClement Courbet }
100cc5e6a72SClement Courbet #endif
101cc5e6a72SClement Courbet 
102cc5e6a72SClement Courbet } // namespace mca
103cc5e6a72SClement Courbet } // namespace llvm
104