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