blob: 06290141739e5663a8e53f39e5002e0bd66fc948 [file] [log] [blame]
Andrew Walbran16937d02019-10-22 13:54:20 +01001//===---------------------- RetireControlUnit.h -----------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9///
10/// This file simulates the hardware responsible for retiring instructions.
11///
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_MCA_RETIRE_CONTROL_UNIT_H
15#define LLVM_MCA_RETIRE_CONTROL_UNIT_H
16
17#include "llvm/MC/MCSchedule.h"
18#include "llvm/MCA/HardwareUnits/HardwareUnit.h"
19#include "llvm/MCA/Instruction.h"
20#include <vector>
21
22namespace llvm {
23namespace mca {
24
25/// This class tracks which instructions are in-flight (i.e., dispatched but not
26/// retired) in the OoO backend.
27//
28/// This class checks on every cycle if/which instructions can be retired.
29/// Instructions are retired in program order.
30/// In the event of an instruction being retired, the pipeline that owns
31/// this RetireControlUnit (RCU) gets notified.
32///
33/// On instruction retired, register updates are all architecturally
34/// committed, and any physicall registers previously allocated for the
35/// retired instruction are freed.
36struct RetireControlUnit : public HardwareUnit {
37 // A RUToken is created by the RCU for every instruction dispatched to the
38 // schedulers. These "tokens" are managed by the RCU in its token Queue.
39 //
40 // On every cycle ('cycleEvent'), the RCU iterates through the token queue
41 // looking for any token with its 'Executed' flag set. If a token has that
42 // flag set, then the instruction has reached the write-back stage and will
43 // be retired by the RCU.
44 //
45 // 'NumSlots' represents the number of entries consumed by the instruction in
46 // the reorder buffer. Those entries will become available again once the
47 // instruction is retired.
48 //
49 // Note that the size of the reorder buffer is defined by the scheduling
50 // model via field 'NumMicroOpBufferSize'.
51 struct RUToken {
52 InstRef IR;
53 unsigned NumSlots; // Slots reserved to this instruction.
54 bool Executed; // True if the instruction is past the WB stage.
55 };
56
57private:
58 unsigned NextAvailableSlotIdx;
59 unsigned CurrentInstructionSlotIdx;
60 unsigned AvailableSlots;
61 unsigned MaxRetirePerCycle; // 0 means no limit.
62 std::vector<RUToken> Queue;
63
64public:
65 RetireControlUnit(const MCSchedModel &SM);
66
67 bool isEmpty() const { return AvailableSlots == Queue.size(); }
68 bool isAvailable(unsigned Quantity = 1) const {
69 // Some instructions may declare a number of uOps which exceeds the size
70 // of the reorder buffer. To avoid problems, cap the amount of slots to
71 // the size of the reorder buffer.
72 Quantity = std::min(Quantity, static_cast<unsigned>(Queue.size()));
73
74 // Further normalize the number of micro opcodes for instructions that
75 // declare zero opcodes. This should match the behavior of method
76 // reserveSlot().
77 Quantity = std::max(Quantity, 1U);
78 return AvailableSlots >= Quantity;
79 }
80
81 unsigned getMaxRetirePerCycle() const { return MaxRetirePerCycle; }
82
83 // Reserves a number of slots, and returns a new token.
84 unsigned reserveSlot(const InstRef &IS, unsigned NumMicroOps);
85
86 // Return the current token from the RCU's circular token queue.
87 const RUToken &peekCurrentToken() const;
88
89 // Advance the pointer to the next token in the circular token queue.
90 void consumeCurrentToken();
91
92 // Update the RCU token to represent the executed state.
93 void onInstructionExecuted(unsigned TokenID);
94
95#ifndef NDEBUG
96 void dump() const;
97#endif
98};
99
100} // namespace mca
101} // namespace llvm
102
103#endif // LLVM_MCA_RETIRE_CONTROL_UNIT_H