1cc5e6a72SClement Courbet //===--------------------- Pipeline.cpp -------------------------*- C++ -*-===// 2cc5e6a72SClement Courbet // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6cc5e6a72SClement Courbet // 7cc5e6a72SClement Courbet //===----------------------------------------------------------------------===// 8cc5e6a72SClement Courbet /// \file 9cc5e6a72SClement Courbet /// 10cc5e6a72SClement Courbet /// This file implements an ordered container of stages that simulate the 11cc5e6a72SClement Courbet /// pipeline of a hardware backend. 12cc5e6a72SClement Courbet /// 13cc5e6a72SClement Courbet //===----------------------------------------------------------------------===// 14cc5e6a72SClement Courbet 15cc5e6a72SClement Courbet #include "llvm/MCA/Pipeline.h" 16cc5e6a72SClement Courbet #include "llvm/MCA/HWEventListener.h" 17cc5e6a72SClement Courbet #include "llvm/Support/Debug.h" 18cc5e6a72SClement Courbet 19cc5e6a72SClement Courbet namespace llvm { 20cc5e6a72SClement Courbet namespace mca { 21cc5e6a72SClement Courbet 22cc5e6a72SClement Courbet #define DEBUG_TYPE "llvm-mca" 23cc5e6a72SClement Courbet addEventListener(HWEventListener * Listener)24cc5e6a72SClement Courbetvoid Pipeline::addEventListener(HWEventListener *Listener) { 25cc5e6a72SClement Courbet if (Listener) 26cc5e6a72SClement Courbet Listeners.insert(Listener); 27cc5e6a72SClement Courbet for (auto &S : Stages) 28cc5e6a72SClement Courbet S->addListener(Listener); 29cc5e6a72SClement Courbet } 30cc5e6a72SClement Courbet hasWorkToProcess()31cc5e6a72SClement Courbetbool Pipeline::hasWorkToProcess() { 32cc5e6a72SClement Courbet return any_of(Stages, [](const std::unique_ptr<Stage> &S) { 33cc5e6a72SClement Courbet return S->hasWorkToComplete(); 34cc5e6a72SClement Courbet }); 35cc5e6a72SClement Courbet } 36cc5e6a72SClement Courbet run()37cc5e6a72SClement CourbetExpected<unsigned> Pipeline::run() { 38cc5e6a72SClement Courbet assert(!Stages.empty() && "Unexpected empty pipeline found!"); 39cc5e6a72SClement Courbet 40cc5e6a72SClement Courbet do { 41*97579dccSMin-Yih Hsu if (!isPaused()) 42cc5e6a72SClement Courbet notifyCycleBegin(); 43cc5e6a72SClement Courbet if (Error Err = runCycle()) 4444a13f33SAndrea Di Biagio return std::move(Err); 45cc5e6a72SClement Courbet notifyCycleEnd(); 46cc5e6a72SClement Courbet ++Cycles; 47cc5e6a72SClement Courbet } while (hasWorkToProcess()); 48cc5e6a72SClement Courbet 49cc5e6a72SClement Courbet return Cycles; 50cc5e6a72SClement Courbet } 51cc5e6a72SClement Courbet runCycle()52cc5e6a72SClement CourbetError Pipeline::runCycle() { 53cc5e6a72SClement Courbet Error Err = ErrorSuccess(); 54cc5e6a72SClement Courbet // Update stages before we start processing new instructions. 55cc5e6a72SClement Courbet for (auto I = Stages.rbegin(), E = Stages.rend(); I != E && !Err; ++I) { 56cc5e6a72SClement Courbet const std::unique_ptr<Stage> &S = *I; 57*97579dccSMin-Yih Hsu if (isPaused()) 58*97579dccSMin-Yih Hsu Err = S->cycleResume(); 59*97579dccSMin-Yih Hsu else 60cc5e6a72SClement Courbet Err = S->cycleStart(); 61cc5e6a72SClement Courbet } 62cc5e6a72SClement Courbet 63*97579dccSMin-Yih Hsu CurrentState = State::Started; 64*97579dccSMin-Yih Hsu 65cc5e6a72SClement Courbet // Now fetch and execute new instructions. 66cc5e6a72SClement Courbet InstRef IR; 67cc5e6a72SClement Courbet Stage &FirstStage = *Stages[0]; 68cc5e6a72SClement Courbet while (!Err && FirstStage.isAvailable(IR)) 69cc5e6a72SClement Courbet Err = FirstStage.execute(IR); 70cc5e6a72SClement Courbet 71*97579dccSMin-Yih Hsu if (Err.isA<InstStreamPause>()) { 72*97579dccSMin-Yih Hsu CurrentState = State::Paused; 73*97579dccSMin-Yih Hsu return Err; 74*97579dccSMin-Yih Hsu } 75*97579dccSMin-Yih Hsu 76cc5e6a72SClement Courbet // Update stages in preparation for a new cycle. 77333a3264SAndrea Di Biagio for (const std::unique_ptr<Stage> &S : Stages) { 78a194656fSAndrea Di Biagio Err = S->cycleEnd(); 79a194656fSAndrea Di Biagio if (Err) 80333a3264SAndrea Di Biagio break; 81cc5e6a72SClement Courbet } 82cc5e6a72SClement Courbet 83cc5e6a72SClement Courbet return Err; 84cc5e6a72SClement Courbet } 85cc5e6a72SClement Courbet appendStage(std::unique_ptr<Stage> S)86cc5e6a72SClement Courbetvoid Pipeline::appendStage(std::unique_ptr<Stage> S) { 87cc5e6a72SClement Courbet assert(S && "Invalid null stage in input!"); 88cc5e6a72SClement Courbet if (!Stages.empty()) { 89cc5e6a72SClement Courbet Stage *Last = Stages.back().get(); 90cc5e6a72SClement Courbet Last->setNextInSequence(S.get()); 91cc5e6a72SClement Courbet } 92cc5e6a72SClement Courbet 93cc5e6a72SClement Courbet Stages.push_back(std::move(S)); 94cc5e6a72SClement Courbet } 95cc5e6a72SClement Courbet notifyCycleBegin()96cc5e6a72SClement Courbetvoid Pipeline::notifyCycleBegin() { 9797ed076dSAndrea Di Biagio LLVM_DEBUG(dbgs() << "\n[E] Cycle begin: " << Cycles << '\n'); 98cc5e6a72SClement Courbet for (HWEventListener *Listener : Listeners) 99cc5e6a72SClement Courbet Listener->onCycleBegin(); 100cc5e6a72SClement Courbet } 101cc5e6a72SClement Courbet notifyCycleEnd()102cc5e6a72SClement Courbetvoid Pipeline::notifyCycleEnd() { 10397ed076dSAndrea Di Biagio LLVM_DEBUG(dbgs() << "[E] Cycle end: " << Cycles << "\n"); 104cc5e6a72SClement Courbet for (HWEventListener *Listener : Listeners) 105cc5e6a72SClement Courbet Listener->onCycleEnd(); 106cc5e6a72SClement Courbet } 107cc5e6a72SClement Courbet } // namespace mca. 108cc5e6a72SClement Courbet } // namespace llvm 109