Path: blob/main/contrib/llvm-project/llvm/lib/MCA/HardwareUnits/RetireControlUnit.cpp
35292 views
//===---------------------- RetireControlUnit.cpp ---------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7/// \file8///9/// This file simulates the hardware responsible for retiring instructions.10///11//===----------------------------------------------------------------------===//1213#include "llvm/MCA/HardwareUnits/RetireControlUnit.h"14#include "llvm/Support/Debug.h"1516#define DEBUG_TYPE "llvm-mca"1718namespace llvm {19namespace mca {2021RetireControlUnit::RetireControlUnit(const MCSchedModel &SM)22: NextAvailableSlotIdx(0), CurrentInstructionSlotIdx(0),23AvailableEntries(SM.isOutOfOrder() ? SM.MicroOpBufferSize : 0),24MaxRetirePerCycle(0) {25assert(SM.isOutOfOrder() &&26"RetireControlUnit is not available for in-order processors");27// Check if the scheduling model provides extra information about the machine28// processor. If so, then use that information to set the reorder buffer size29// and the maximum number of instructions retired per cycle.30if (SM.hasExtraProcessorInfo()) {31const MCExtraProcessorInfo &EPI = SM.getExtraProcessorInfo();32if (EPI.ReorderBufferSize)33AvailableEntries = EPI.ReorderBufferSize;34MaxRetirePerCycle = EPI.MaxRetirePerCycle;35}36NumROBEntries = AvailableEntries;37assert(NumROBEntries && "Invalid reorder buffer size!");38Queue.resize(2 * NumROBEntries);39}4041// Reserves a number of slots, and returns a new token.42unsigned RetireControlUnit::dispatch(const InstRef &IR) {43const Instruction &Inst = *IR.getInstruction();44unsigned Entries = normalizeQuantity(Inst.getNumMicroOps());45assert((AvailableEntries >= Entries) && "Reorder Buffer unavailable!");4647unsigned TokenID = NextAvailableSlotIdx;48Queue[NextAvailableSlotIdx] = {IR, Entries, false};49NextAvailableSlotIdx += std::max(1U, Entries);50NextAvailableSlotIdx %= Queue.size();51assert(TokenID < UnhandledTokenID && "Invalid token ID");5253AvailableEntries -= Entries;54return TokenID;55}5657const RetireControlUnit::RUToken &RetireControlUnit::getCurrentToken() const {58const RetireControlUnit::RUToken &Current = Queue[CurrentInstructionSlotIdx];59#ifndef NDEBUG60const Instruction *Inst = Current.IR.getInstruction();61assert(Inst && "Invalid RUToken in the RCU queue.");62#endif63return Current;64}6566unsigned RetireControlUnit::computeNextSlotIdx() const {67const RetireControlUnit::RUToken &Current = getCurrentToken();68unsigned NextSlotIdx = CurrentInstructionSlotIdx + std::max(1U, Current.NumSlots);69return NextSlotIdx % Queue.size();70}7172const RetireControlUnit::RUToken &RetireControlUnit::peekNextToken() const {73return Queue[computeNextSlotIdx()];74}7576void RetireControlUnit::consumeCurrentToken() {77RetireControlUnit::RUToken &Current = Queue[CurrentInstructionSlotIdx];78Current.IR.getInstruction()->retire();7980// Update the slot index to be the next item in the circular queue.81CurrentInstructionSlotIdx += std::max(1U, Current.NumSlots);82CurrentInstructionSlotIdx %= Queue.size();83AvailableEntries += Current.NumSlots;84Current = { InstRef(), 0U, false };85}8687void RetireControlUnit::onInstructionExecuted(unsigned TokenID) {88assert(Queue.size() > TokenID);89assert(Queue[TokenID].IR.getInstruction() && "Instruction was not dispatched!");90assert(Queue[TokenID].Executed == false && "Instruction already executed!");91Queue[TokenID].Executed = true;92}9394#ifndef NDEBUG95void RetireControlUnit::dump() const {96dbgs() << "Retire Unit: { Total ROB Entries =" << NumROBEntries97<< ", Available ROB entries=" << AvailableEntries << " }\n";98}99#endif100101} // namespace mca102} // namespace llvm103104105