blob: d4c42742c42ef970c220973283616685c886acb2 [file] [log] [blame]
Andrea Di Biagioe2492c82018-05-15 09:31:32 +00001//===---------------------- 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///
Matt Davis5b79ffc5b2018-05-25 18:00:25 +000011/// This file simulates the hardware responsible for retiring instructions.
Andrea Di Biagioe2492c82018-05-15 09:31:32 +000012///
13//===----------------------------------------------------------------------===//
14
Andrea Di Biagio904684c2018-05-15 10:30:39 +000015#include "RetireControlUnit.h"
Matt Davis679083e2018-05-17 19:22:29 +000016#include "DispatchStage.h"
Matt Davis6aa5dcd2018-05-01 23:04:01 +000017#include "llvm/Support/Debug.h"
18
19using namespace llvm;
20
21#define DEBUG_TYPE "llvm-mca"
22
23namespace mca {
24
Matt Davis5b79ffc5b2018-05-25 18:00:25 +000025RetireControlUnit::RetireControlUnit(const llvm::MCSchedModel &SM)
Matt Davis6aa5dcd2018-05-01 23:04:01 +000026 : NextAvailableSlotIdx(0), CurrentInstructionSlotIdx(0),
Matt Davis5b79ffc5b2018-05-25 18:00:25 +000027 AvailableSlots(SM.MicroOpBufferSize), MaxRetirePerCycle(0) {
Matt Davis6aa5dcd2018-05-01 23:04:01 +000028 // Check if the scheduling model provides extra information about the machine
29 // processor. If so, then use that information to set the reorder buffer size
30 // and the maximum number of instructions retired per cycle.
31 if (SM.hasExtraProcessorInfo()) {
32 const MCExtraProcessorInfo &EPI = SM.getExtraProcessorInfo();
33 if (EPI.ReorderBufferSize)
34 AvailableSlots = EPI.ReorderBufferSize;
35 MaxRetirePerCycle = EPI.MaxRetirePerCycle;
36 }
37
38 assert(AvailableSlots && "Invalid reorder buffer size!");
39 Queue.resize(AvailableSlots);
40}
41
42// Reserves a number of slots, and returns a new token.
Andrea Di Biagio904684c2018-05-15 10:30:39 +000043unsigned RetireControlUnit::reserveSlot(const InstRef &IR,
44 unsigned NumMicroOps) {
Matt Davis6aa5dcd2018-05-01 23:04:01 +000045 assert(isAvailable(NumMicroOps));
46 unsigned NormalizedQuantity =
47 std::min(NumMicroOps, static_cast<unsigned>(Queue.size()));
48 // Zero latency instructions may have zero mOps. Artificially bump this
49 // value to 1. Although zero latency instructions don't consume scheduler
50 // resources, they still consume one slot in the retire queue.
51 NormalizedQuantity = std::max(NormalizedQuantity, 1U);
52 unsigned TokenID = NextAvailableSlotIdx;
Matt Davis21a8d322018-05-07 18:29:15 +000053 Queue[NextAvailableSlotIdx] = {IR, NormalizedQuantity, false};
Matt Davis6aa5dcd2018-05-01 23:04:01 +000054 NextAvailableSlotIdx += NormalizedQuantity;
55 NextAvailableSlotIdx %= Queue.size();
56 AvailableSlots -= NormalizedQuantity;
57 return TokenID;
58}
59
Matt Davis5b79ffc5b2018-05-25 18:00:25 +000060const RetireControlUnit::RUToken &RetireControlUnit::peekCurrentToken() const {
61 return Queue[CurrentInstructionSlotIdx];
62}
Matt Davis6aa5dcd2018-05-01 23:04:01 +000063
Matt Davis5b79ffc5b2018-05-25 18:00:25 +000064void RetireControlUnit::consumeCurrentToken() {
65 const RetireControlUnit::RUToken &Current = peekCurrentToken();
66 assert(Current.NumSlots && "Reserved zero slots?");
67 assert(Current.IR.isValid() && "Invalid RUToken in the RCU queue.");
68
69 // Update the slot index to be the next item in the circular queue.
70 CurrentInstructionSlotIdx += Current.NumSlots;
71 CurrentInstructionSlotIdx %= Queue.size();
72 AvailableSlots += Current.NumSlots;
Matt Davis6aa5dcd2018-05-01 23:04:01 +000073}
74
75void RetireControlUnit::onInstructionExecuted(unsigned TokenID) {
76 assert(Queue.size() > TokenID);
Matt Davis21a8d322018-05-07 18:29:15 +000077 assert(Queue[TokenID].Executed == false && Queue[TokenID].IR.isValid());
Matt Davis6aa5dcd2018-05-01 23:04:01 +000078 Queue[TokenID].Executed = true;
79}
80
81#ifndef NDEBUG
82void RetireControlUnit::dump() const {
83 dbgs() << "Retire Unit: { Total Slots=" << Queue.size()
84 << ", Available Slots=" << AvailableSlots << " }\n";
85}
86#endif
87
88} // namespace mca