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