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: getListeners()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. isAvailable(const InstRef & IR)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. cycleStart()49 virtual Error cycleStart() { return ErrorSuccess(); } 50 51 /// Called after the pipeline is resumed from pausing state. cycleResume()52 virtual Error cycleResume() { return ErrorSuccess(); } 53 54 /// Called once at the end of each cycle. cycleEnd()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 setNextInSequence(Stage * NextStage)60 void setNextInSequence(Stage *NextStage) { 61 assert(!NextInSequence && "This stage already has a NextInSequence!"); 62 NextInSequence = NextStage; 63 } 64 checkNextStage(const InstRef & IR)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. moveToTheNextStage(InstRef & IR)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. notifyEvent(const EventT & 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 convertToErrorCodeInstStreamPause93 std::error_code convertToErrorCode() const override { 94 return llvm::inconvertibleErrorCode(); 95 } logInstStreamPause96 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