1 | //===---------------------- Stage.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 defines a stage. |
11 | /// A chain of stages compose an instruction pipeline. |
12 | /// |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #ifndef LLVM_MCA_STAGES_STAGE_H |
16 | #define LLVM_MCA_STAGES_STAGE_H |
17 | |
18 | #include "llvm/MCA/HWEventListener.h" |
19 | #include "llvm/Support/Error.h" |
20 | #include <set> |
21 | |
22 | namespace llvm { |
23 | namespace mca { |
24 | |
25 | class InstRef; |
26 | |
27 | class Stage { |
28 | Stage *NextInSequence = nullptr; |
29 | std::set<HWEventListener *> Listeners; |
30 | |
31 | Stage(const Stage &Other) = delete; |
32 | Stage &operator=(const Stage &Other) = delete; |
33 | |
34 | protected: |
35 | const std::set<HWEventListener *> &getListeners() const { return Listeners; } |
36 | |
37 | public: |
38 | Stage() = default; |
39 | virtual ~Stage(); |
40 | |
41 | /// Returns true if it can execute IR during this cycle. |
42 | virtual bool isAvailable(const InstRef &IR) const { return true; } |
43 | |
44 | /// Returns true if some instructions are still executing this stage. |
45 | virtual bool hasWorkToComplete() const = 0; |
46 | |
47 | /// Called once at the start of each cycle. This can be used as a setup |
48 | /// phase to prepare for the executions during the cycle. |
49 | virtual Error cycleStart() { return ErrorSuccess(); } |
50 | |
51 | /// Called after the pipeline is resumed from pausing state. |
52 | virtual Error cycleResume() { return ErrorSuccess(); } |
53 | |
54 | /// Called once at the end of each cycle. |
55 | virtual Error cycleEnd() { return ErrorSuccess(); } |
56 | |
57 | /// The primary action that this stage performs on instruction IR. |
58 | virtual Error execute(InstRef &IR) = 0; |
59 | |
60 | void setNextInSequence(Stage *NextStage) { |
61 | assert(!NextInSequence && "This stage already has a NextInSequence!" ); |
62 | NextInSequence = NextStage; |
63 | } |
64 | |
65 | bool checkNextStage(const InstRef &IR) const { |
66 | return NextInSequence && NextInSequence->isAvailable(IR); |
67 | } |
68 | |
69 | /// Called when an instruction is ready to move the next pipeline stage. |
70 | /// |
71 | /// Stages are responsible for moving instructions to their immediate |
72 | /// successor stages. |
73 | Error moveToTheNextStage(InstRef &IR) { |
74 | assert(checkNextStage(IR) && "Next stage is not ready!" ); |
75 | return NextInSequence->execute(IR); |
76 | } |
77 | |
78 | /// Add a listener to receive callbacks during the execution of this stage. |
79 | void addListener(HWEventListener *Listener); |
80 | |
81 | /// Notify listeners of a particular hardware event. |
82 | template <typename EventT> void notifyEvent(const EventT &Event) const { |
83 | for (HWEventListener *Listener : Listeners) |
84 | Listener->onEvent(Event); |
85 | } |
86 | }; |
87 | |
88 | /// This is actually not an error but a marker to indicate that |
89 | /// the instruction stream is paused. |
90 | struct InstStreamPause : public ErrorInfo<InstStreamPause> { |
91 | static char ID; |
92 | |
93 | std::error_code convertToErrorCode() const override { |
94 | return llvm::inconvertibleErrorCode(); |
95 | } |
96 | void log(raw_ostream &OS) const override { OS << "Stream is paused" ; } |
97 | }; |
98 | } // namespace mca |
99 | } // namespace llvm |
100 | #endif // LLVM_MCA_STAGES_STAGE_H |
101 | |