109 lines · cpp
1//===--------------------- Pipeline.cpp -------------------------*- 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-exception6//7//===----------------------------------------------------------------------===//8/// \file9///10/// This file implements an ordered container of stages that simulate the11/// pipeline of a hardware backend.12///13//===----------------------------------------------------------------------===//14 15#include "llvm/MCA/Pipeline.h"16#include "llvm/MCA/HWEventListener.h"17#include "llvm/Support/Debug.h"18 19namespace llvm {20namespace mca {21 22#define DEBUG_TYPE "llvm-mca"23 24void Pipeline::addEventListener(HWEventListener *Listener) {25 if (Listener)26 Listeners.insert(Listener);27 for (auto &S : Stages)28 S->addListener(Listener);29}30 31bool Pipeline::hasWorkToProcess() {32 return any_of(Stages, [](const std::unique_ptr<Stage> &S) {33 return S->hasWorkToComplete();34 });35}36 37Expected<unsigned> Pipeline::run() {38 assert(!Stages.empty() && "Unexpected empty pipeline found!");39 40 do {41 if (!isPaused())42 notifyCycleBegin();43 if (Error Err = runCycle())44 return std::move(Err);45 notifyCycleEnd();46 ++Cycles;47 } while (hasWorkToProcess());48 49 return Cycles;50}51 52Error Pipeline::runCycle() {53 Error Err = ErrorSuccess();54 // Update stages before we start processing new instructions.55 for (auto I = Stages.rbegin(), E = Stages.rend(); I != E && !Err; ++I) {56 const std::unique_ptr<Stage> &S = *I;57 if (isPaused())58 Err = S->cycleResume();59 else60 Err = S->cycleStart();61 }62 63 CurrentState = State::Started;64 65 // Now fetch and execute new instructions.66 InstRef IR;67 Stage &FirstStage = *Stages[0];68 while (!Err && FirstStage.isAvailable(IR))69 Err = FirstStage.execute(IR);70 71 if (Err.isA<InstStreamPause>()) {72 CurrentState = State::Paused;73 return Err;74 }75 76 // Update stages in preparation for a new cycle.77 for (const std::unique_ptr<Stage> &S : Stages) {78 Err = S->cycleEnd();79 if (Err)80 break;81 }82 83 return Err;84}85 86void Pipeline::appendStage(std::unique_ptr<Stage> S) {87 assert(S && "Invalid null stage in input!");88 if (!Stages.empty()) {89 Stage *Last = Stages.back().get();90 Last->setNextInSequence(S.get());91 }92 93 Stages.push_back(std::move(S));94}95 96void Pipeline::notifyCycleBegin() {97 LLVM_DEBUG(dbgs() << "\n[E] Cycle begin: " << Cycles << '\n');98 for (HWEventListener *Listener : Listeners)99 Listener->onCycleBegin();100}101 102void Pipeline::notifyCycleEnd() {103 LLVM_DEBUG(dbgs() << "[E] Cycle end: " << Cycles << "\n");104 for (HWEventListener *Listener : Listeners)105 Listener->onCycleEnd();106}107} // namespace mca.108} // namespace llvm109