155682Smarkm//===--------------------- Pipeline.cpp -------------------------*- C++ -*-===// 2233294Sstas// 3233294Sstas// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4233294Sstas// See https://llvm.org/LICENSE.txt for license information. 555682Smarkm// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6233294Sstas// 7233294Sstas//===----------------------------------------------------------------------===// 8233294Sstas/// \file 955682Smarkm/// 10233294Sstas/// This file implements an ordered container of stages that simulate the 11233294Sstas/// pipeline of a hardware backend. 1255682Smarkm/// 13233294Sstas//===----------------------------------------------------------------------===// 14233294Sstas 15233294Sstas#include "llvm/MCA/Pipeline.h" 1655682Smarkm#include "llvm/MCA/HWEventListener.h" 1755682Smarkm#include "llvm/Support/Debug.h" 1855682Smarkm 1955682Smarkmnamespace llvm { 2055682Smarkmnamespace mca { 2155682Smarkm 2255682Smarkm#define DEBUG_TYPE "llvm-mca" 2355682Smarkm 2455682Smarkmvoid Pipeline::addEventListener(HWEventListener *Listener) { 2555682Smarkm if (Listener) 2655682Smarkm Listeners.insert(Listener); 2755682Smarkm for (auto &S : Stages) 2855682Smarkm S->addListener(Listener); 2955682Smarkm} 3055682Smarkm 3155682Smarkmbool Pipeline::hasWorkToProcess() { 3255682Smarkm return any_of(Stages, [](const std::unique_ptr<Stage> &S) { 3355682Smarkm return S->hasWorkToComplete(); 34233294Sstas }); 35178825Sdfr} 36178825Sdfr 37178825SdfrExpected<unsigned> Pipeline::run() { 3855682Smarkm assert(!Stages.empty() && "Unexpected empty pipeline found!"); 3955682Smarkm 4055682Smarkm do { 4155682Smarkm notifyCycleBegin(); 4255682Smarkm if (Error Err = runCycle()) 4355682Smarkm return std::move(Err); 4455682Smarkm notifyCycleEnd(); 4555682Smarkm ++Cycles; 4655682Smarkm } while (hasWorkToProcess()); 4755682Smarkm 4855682Smarkm return Cycles; 4955682Smarkm} 5055682Smarkm 5155682SmarkmError Pipeline::runCycle() { 5255682Smarkm Error Err = ErrorSuccess(); 5355682Smarkm // Update stages before we start processing new instructions. 5455682Smarkm for (auto I = Stages.rbegin(), E = Stages.rend(); I != E && !Err; ++I) { 5555682Smarkm const std::unique_ptr<Stage> &S = *I; 5655682Smarkm Err = S->cycleStart(); 5755682Smarkm } 5855682Smarkm 5955682Smarkm // Now fetch and execute new instructions. 6055682Smarkm InstRef IR; 6155682Smarkm Stage &FirstStage = *Stages[0]; 6255682Smarkm while (!Err && FirstStage.isAvailable(IR)) 6355682Smarkm Err = FirstStage.execute(IR); 6455682Smarkm 6555682Smarkm // Update stages in preparation for a new cycle. 6655682Smarkm for (const std::unique_ptr<Stage> &S : Stages) { 6755682Smarkm Err = S->cycleEnd(); 6855682Smarkm if (Err) 6955682Smarkm break; 7055682Smarkm } 7155682Smarkm 7255682Smarkm return Err; 7355682Smarkm} 7455682Smarkm 7555682Smarkmvoid Pipeline::appendStage(std::unique_ptr<Stage> S) { 7655682Smarkm assert(S && "Invalid null stage in input!"); 7755682Smarkm if (!Stages.empty()) { 7855682Smarkm Stage *Last = Stages.back().get(); 7955682Smarkm Last->setNextInSequence(S.get()); 8055682Smarkm } 81178825Sdfr 8255682Smarkm Stages.push_back(std::move(S)); 8355682Smarkm} 8455682Smarkm 8555682Smarkmvoid Pipeline::notifyCycleBegin() { 8655682Smarkm LLVM_DEBUG(dbgs() << "\n[E] Cycle begin: " << Cycles << '\n'); 8755682Smarkm for (HWEventListener *Listener : Listeners) 8855682Smarkm Listener->onCycleBegin(); 8955682Smarkm} 9055682Smarkm 9155682Smarkmvoid Pipeline::notifyCycleEnd() { 9255682Smarkm LLVM_DEBUG(dbgs() << "[E] Cycle end: " << Cycles << "\n"); 9355682Smarkm for (HWEventListener *Listener : Listeners) 9455682Smarkm Listener->onCycleEnd(); 9555682Smarkm} 9655682Smarkm} // namespace mca. 9755682Smarkm} // namespace llvm 9855682Smarkm