Index: tools/llvm-mca/CMakeLists.txt =================================================================== --- tools/llvm-mca/CMakeLists.txt +++ tools/llvm-mca/CMakeLists.txt @@ -11,6 +11,7 @@ add_llvm_tool(llvm-mca CodeRegion.cpp + Context.cpp DispatchStage.cpp DispatchStatistics.cpp ExecuteStage.cpp Index: tools/llvm-mca/Context.h =================================================================== --- /dev/null +++ tools/llvm-mca/Context.h @@ -0,0 +1,52 @@ +//===---------------------------- Context.h ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file defines a class for holding ownership of various simulated +/// hardware components. A Context also provides utility routines that make +/// use of its simulated hardware components. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVM_MCA_CONTEXT_H +#define LLVM_TOOLS_LLVM_MCA_CONTEXT_H +#include "HardwareUnit.h" +#include "InstrBuilder.h" +#include "Pipeline.h" +#include "SourceMgr.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSchedule.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include + +namespace mca { + +class Context { + llvm::SmallVector, 4> Hardware; + +public: + Context() = default; + Context(const Context &C) = delete; + Context &operator=(const Context &C) = delete; + + void addHardware(std::unique_ptr H) { + Hardware.push_back(std::move(H)); + } + + /// Construct a basic pipeline for simulating an out-of-order pipeline. + /// This pipeline consists of Fetch, Dispatch, Execute, and Retire stages. + std::unique_ptr createDefaultPipeline( + unsigned DispatchWidth, unsigned RegisterFileSize, unsigned LoadQueueSize, + unsigned StoreQueueSize, bool AssumeNoAlias, SourceMgr &Src, + InstrBuilder &IB, const llvm::MCSchedModel &SM, + const llvm::MCSubtargetInfo &STI, const llvm::MCRegisterInfo &MRI); +}; + +} // namespace mca +#endif // LLVM_TOOLS_LLVM_MCA_CONTEXT_H Index: tools/llvm-mca/Context.cpp =================================================================== --- /dev/null +++ tools/llvm-mca/Context.cpp @@ -0,0 +1,64 @@ +//===---------------------------- Context.cpp -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file defines a class for holding ownership of various simulated +/// hardware components. A Context also provides utility routines that make +/// use of its simulated hardware components. +/// +//===----------------------------------------------------------------------===// + +#include "Context.h" +#include "DispatchStage.h" +#include "ExecuteStage.h" +#include "FetchStage.h" +#include "RegisterFile.h" +#include "RetireControlUnit.h" +#include "RetireStage.h" +#include "Scheduler.h" + +namespace mca { + +using namespace llvm; + +// Construct a simple pipeline for simulating an out-of-order backend. +std::unique_ptr Context::createDefaultPipeline( + unsigned DispatchWidth, unsigned RegisterFileSize, unsigned LoadQueueSize, + unsigned StoreQueueSize, bool AssumeNoAlias, SourceMgr &Src, + InstrBuilder &IB, const MCSchedModel &SM, const MCSubtargetInfo &STI, + const MCRegisterInfo &MRI) { + // Create the hardware components defining the backend. + auto RCU = llvm::make_unique(SM); + auto PRF = llvm::make_unique(SM, MRI, RegisterFileSize); + auto HWS = llvm::make_unique(SM, LoadQueueSize, StoreQueueSize, + AssumeNoAlias); + // Create the pipeline and its stages. + auto P = + llvm::make_unique(DispatchWidth, RegisterFileSize, + LoadQueueSize, StoreQueueSize, AssumeNoAlias); + auto F = llvm::make_unique(IB, Src); + auto D = llvm::make_unique(STI, MRI, RegisterFileSize, + DispatchWidth, *RCU, *PRF, *HWS); + auto R = llvm::make_unique(*RCU, *PRF); + auto E = llvm::make_unique(*RCU, *HWS); + + // Add the hardware to the context. + addHardware(std::move(RCU)); + addHardware(std::move(PRF)); + addHardware(std::move(HWS)); + + // Build the pipeline. + P->appendStage(std::move(F)); + P->appendStage(std::move(D)); + P->appendStage(std::move(R)); + P->appendStage(std::move(E)); + return P; +} + +} // namespace mca Index: tools/llvm-mca/HardwareUnit.h =================================================================== --- /dev/null +++ tools/llvm-mca/HardwareUnit.h @@ -0,0 +1,29 @@ +//===-------------------------- HardwareUnit.h ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file defines a base class for describing a simulated hardware +/// component. These components are used to construct a simulated backend. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVM_MCA_HARDWAREUNIT_H +#define LLVM_TOOLS_LLVM_MCA_HARDWAREUNIT_H + +namespace mca { + +struct HardwareUnit { + HardwareUnit() = default; + HardwareUnit(const HardwareUnit &H) = delete; + HardwareUnit &operator=(const HardwareUnit &H) = delete; + virtual ~HardwareUnit() = default; +}; + +} // namespace mca +#endif // LLVM_TOOLS_LLVM_MCA_HARDWAREUNIT_H Index: tools/llvm-mca/RegisterFile.h =================================================================== --- tools/llvm-mca/RegisterFile.h +++ tools/llvm-mca/RegisterFile.h @@ -17,6 +17,7 @@ #ifndef LLVM_TOOLS_LLVM_MCA_REGISTER_FILE_H #define LLVM_TOOLS_LLVM_MCA_REGISTER_FILE_H +#include "HardwareUnit.h" #include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSchedule.h" @@ -28,10 +29,11 @@ /// Manages hardware register files, and tracks register definitions for /// register renaming purposes. -class RegisterFile { +class RegisterFile : public HardwareUnit { const llvm::MCRegisterInfo &MRI; - // Each register file is associated with an instance of RegisterMappingTracker. + // Each register file is associated with an instance of + // RegisterMappingTracker. // A RegisterMappingTracker keeps track of the number of physical registers // which have been dynamically allocated by the simulator. struct RegisterMappingTracker { @@ -53,7 +55,7 @@ // hardware registers declared by the target (i.e. all the register // definitions in the target specific `XYZRegisterInfo.td` - where `XYZ` is // the target name). - // + // // Users can limit the number of physical registers that are available in // regsiter file #0 specifying command line flag `-register-file-size=`. llvm::SmallVector RegisterFiles; Index: tools/llvm-mca/RetireControlUnit.h =================================================================== --- tools/llvm-mca/RetireControlUnit.h +++ tools/llvm-mca/RetireControlUnit.h @@ -15,6 +15,7 @@ #ifndef LLVM_TOOLS_LLVM_MCA_RETIRE_CONTROL_UNIT_H #define LLVM_TOOLS_LLVM_MCA_RETIRE_CONTROL_UNIT_H +#include "HardwareUnit.h" #include "Instruction.h" #include "llvm/MC/MCSchedule.h" #include @@ -32,7 +33,7 @@ /// On instruction retired, register updates are all architecturally /// committed, and any temporary registers originally allocated for the /// retired instruction are freed. -struct RetireControlUnit { +struct RetireControlUnit : public HardwareUnit { // A RUToken is created by the RCU for every instruction dispatched to the // schedulers. These "tokens" are managed by the RCU in its token Queue. // Index: tools/llvm-mca/Scheduler.h =================================================================== --- tools/llvm-mca/Scheduler.h +++ tools/llvm-mca/Scheduler.h @@ -16,6 +16,7 @@ #define LLVM_TOOLS_LLVM_MCA_SCHEDULER_H #include "HWEventListener.h" +#include "HardwareUnit.h" #include "Instruction.h" #include "LSUnit.h" #include "RetireControlUnit.h" @@ -401,7 +402,7 @@ /// issued to a (one or more) pipeline(s). This event also causes an instruction /// state transition (i.e. from state IS_READY, to state IS_EXECUTING). /// An Instruction leaves the IssuedQueue when it reaches the write-back stage. -class Scheduler { +class Scheduler : public HardwareUnit { const llvm::MCSchedModel &SM; // Hardware resources that are managed by this scheduler. Index: tools/llvm-mca/llvm-mca.cpp =================================================================== --- tools/llvm-mca/llvm-mca.cpp +++ tools/llvm-mca/llvm-mca.cpp @@ -22,21 +22,15 @@ //===----------------------------------------------------------------------===// #include "CodeRegion.h" -#include "DispatchStage.h" +#include "Context.h" #include "DispatchStatistics.h" -#include "ExecuteStage.h" -#include "FetchStage.h" #include "InstructionInfoView.h" #include "InstructionTables.h" #include "Pipeline.h" #include "PipelinePrinter.h" -#include "RegisterFile.h" #include "RegisterFileStatistics.h" #include "ResourcePressureView.h" -#include "RetireControlUnit.h" #include "RetireControlUnitStatistics.h" -#include "RetireStage.h" -#include "Scheduler.h" #include "SchedulerStatistics.h" #include "SummaryView.h" #include "TimelineView.h" @@ -501,19 +495,11 @@ continue; } - // Create the hardware components required for the pipeline. - mca::RetireControlUnit RCU(SM); - mca::RegisterFile PRF(SM, *MRI, RegisterFileSize); - mca::Scheduler HWS(SM, LoadQueueSize, StoreQueueSize, AssumeNoAlias); - - // Create the pipeline and add stages to it. - auto P = llvm::make_unique( - Width, RegisterFileSize, LoadQueueSize, StoreQueueSize, AssumeNoAlias); - P->appendStage(llvm::make_unique(IB, S)); - P->appendStage(llvm::make_unique( - *STI, *MRI, RegisterFileSize, Width, RCU, PRF, HWS)); - P->appendStage(llvm::make_unique(RCU, PRF)); - P->appendStage(llvm::make_unique(RCU, HWS)); + // Create a basic pipeline simulating an out-of-order backend. + mca::Context Ctx; + auto P = Ctx.createDefaultPipeline(Width, RegisterFileSize, LoadQueueSize, + StoreQueueSize, AssumeNoAlias, S, IB, SM, + *STI, *MRI); mca::PipelinePrinter Printer(*P); if (PrintSummaryView)