• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===---------------------- RetireControlUnit.cpp ---------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 ///
11 /// This file simulates the hardware responsible for retiring instructions.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #include "RetireControlUnit.h"
16 #include "llvm/Support/Debug.h"
17 
18 using namespace llvm;
19 
20 #define DEBUG_TYPE "llvm-mca"
21 
22 namespace mca {
23 
RetireControlUnit(const llvm::MCSchedModel & SM)24 RetireControlUnit::RetireControlUnit(const llvm::MCSchedModel &SM)
25     : NextAvailableSlotIdx(0), CurrentInstructionSlotIdx(0),
26       AvailableSlots(SM.MicroOpBufferSize), MaxRetirePerCycle(0) {
27   // Check if the scheduling model provides extra information about the machine
28   // processor. If so, then use that information to set the reorder buffer size
29   // and the maximum number of instructions retired per cycle.
30   if (SM.hasExtraProcessorInfo()) {
31     const MCExtraProcessorInfo &EPI = SM.getExtraProcessorInfo();
32     if (EPI.ReorderBufferSize)
33       AvailableSlots = EPI.ReorderBufferSize;
34     MaxRetirePerCycle = EPI.MaxRetirePerCycle;
35   }
36 
37   assert(AvailableSlots && "Invalid reorder buffer size!");
38   Queue.resize(AvailableSlots);
39 }
40 
41 // Reserves a number of slots, and returns a new token.
reserveSlot(const InstRef & IR,unsigned NumMicroOps)42 unsigned RetireControlUnit::reserveSlot(const InstRef &IR,
43                                         unsigned NumMicroOps) {
44   assert(isAvailable(NumMicroOps));
45   unsigned NormalizedQuantity =
46       std::min(NumMicroOps, static_cast<unsigned>(Queue.size()));
47   // Zero latency instructions may have zero mOps. Artificially bump this
48   // value to 1. Although zero latency instructions don't consume scheduler
49   // resources, they still consume one slot in the retire queue.
50   NormalizedQuantity = std::max(NormalizedQuantity, 1U);
51   unsigned TokenID = NextAvailableSlotIdx;
52   Queue[NextAvailableSlotIdx] = {IR, NormalizedQuantity, false};
53   NextAvailableSlotIdx += NormalizedQuantity;
54   NextAvailableSlotIdx %= Queue.size();
55   AvailableSlots -= NormalizedQuantity;
56   return TokenID;
57 }
58 
peekCurrentToken() const59 const RetireControlUnit::RUToken &RetireControlUnit::peekCurrentToken() const {
60   return Queue[CurrentInstructionSlotIdx];
61 }
62 
consumeCurrentToken()63 void RetireControlUnit::consumeCurrentToken() {
64   const RetireControlUnit::RUToken &Current = peekCurrentToken();
65   assert(Current.NumSlots && "Reserved zero slots?");
66   assert(Current.IR.isValid() && "Invalid RUToken in the RCU queue.");
67 
68   // Update the slot index to be the next item in the circular queue.
69   CurrentInstructionSlotIdx += Current.NumSlots;
70   CurrentInstructionSlotIdx %= Queue.size();
71   AvailableSlots += Current.NumSlots;
72 }
73 
onInstructionExecuted(unsigned TokenID)74 void RetireControlUnit::onInstructionExecuted(unsigned TokenID) {
75   assert(Queue.size() > TokenID);
76   assert(Queue[TokenID].Executed == false && Queue[TokenID].IR.isValid());
77   Queue[TokenID].Executed = true;
78 }
79 
80 #ifndef NDEBUG
dump() const81 void RetireControlUnit::dump() const {
82   dbgs() << "Retire Unit: { Total Slots=" << Queue.size()
83          << ", Available Slots=" << AvailableSlots << " }\n";
84 }
85 #endif
86 
87 } // namespace mca
88