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; 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: Stage()38 Stage() : NextInSequence(nullptr) {} 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 once at the end of each cycle. cycleEnd()52 virtual Error cycleEnd() { return ErrorSuccess(); } 53 54 /// The primary action that this stage performs on instruction IR. 55 virtual Error execute(InstRef &IR) = 0; 56 setNextInSequence(Stage * NextStage)57 void setNextInSequence(Stage *NextStage) { 58 assert(!NextInSequence && "This stage already has a NextInSequence!"); 59 NextInSequence = NextStage; 60 } 61 checkNextStage(const InstRef & IR)62 bool checkNextStage(const InstRef &IR) const { 63 return NextInSequence && NextInSequence->isAvailable(IR); 64 } 65 66 /// Called when an instruction is ready to move the next pipeline stage. 67 /// 68 /// Stages are responsible for moving instructions to their immediate 69 /// successor stages. moveToTheNextStage(InstRef & IR)70 Error moveToTheNextStage(InstRef &IR) { 71 assert(checkNextStage(IR) && "Next stage is not ready!"); 72 return NextInSequence->execute(IR); 73 } 74 75 /// Add a listener to receive callbacks during the execution of this stage. 76 void addListener(HWEventListener *Listener); 77 78 /// Notify listeners of a particular hardware event. notifyEvent(const EventT & Event)79 template <typename EventT> void notifyEvent(const EventT &Event) const { 80 for (HWEventListener *Listener : Listeners) 81 Listener->onEvent(Event); 82 } 83 }; 84 85 } // namespace mca 86 } // namespace llvm 87 #endif // LLVM_MCA_STAGES_STAGE_H 88