//===--------------------- Pipeline.cpp -------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// \file /// /// This file implements an ordered container of stages that simulate the /// pipeline of a hardware backend. /// //===----------------------------------------------------------------------===// #include "llvm/MCA/Pipeline.h" #include "llvm/MCA/HWEventListener.h" #include "llvm/Support/Debug.h" namespace llvm { namespace mca { #define DEBUG_TYPE "llvm-mca" void Pipeline::addEventListener(HWEventListener *Listener) { if (Listener) Listeners.insert(Listener); for (auto &S : Stages) S->addListener(Listener); } bool Pipeline::hasWorkToProcess() { return any_of(Stages, [](const std::unique_ptr &S) { return S->hasWorkToComplete(); }); } Expected Pipeline::run() { assert(!Stages.empty() && "Unexpected empty pipeline found!"); do { if (!isPaused()) notifyCycleBegin(); if (Error Err = runCycle()) return std::move(Err); notifyCycleEnd(); ++Cycles; } while (hasWorkToProcess()); return Cycles; } Error Pipeline::runCycle() { Error Err = ErrorSuccess(); // Update stages before we start processing new instructions. for (auto I = Stages.rbegin(), E = Stages.rend(); I != E && !Err; ++I) { const std::unique_ptr &S = *I; if (isPaused()) Err = S->cycleResume(); else Err = S->cycleStart(); } CurrentState = State::Started; // Now fetch and execute new instructions. InstRef IR; Stage &FirstStage = *Stages[0]; while (!Err && FirstStage.isAvailable(IR)) Err = FirstStage.execute(IR); if (Err.isA()) { CurrentState = State::Paused; return Err; } // Update stages in preparation for a new cycle. for (const std::unique_ptr &S : Stages) { Err = S->cycleEnd(); if (Err) break; } return Err; } void Pipeline::appendStage(std::unique_ptr S) { assert(S && "Invalid null stage in input!"); if (!Stages.empty()) { Stage *Last = Stages.back().get(); Last->setNextInSequence(S.get()); } Stages.push_back(std::move(S)); } void Pipeline::notifyCycleBegin() { LLVM_DEBUG(dbgs() << "\n[E] Cycle begin: " << Cycles << '\n'); for (HWEventListener *Listener : Listeners) Listener->onCycleBegin(); } void Pipeline::notifyCycleEnd() { LLVM_DEBUG(dbgs() << "[E] Cycle end: " << Cycles << "\n"); for (HWEventListener *Listener : Listeners) Listener->onCycleEnd(); } } // namespace mca. } // namespace llvm