mirror of https://github.com/llvm/circt.git
[firtool] Add infra for pass plugins (#6254)
This PR ads MLIR pass plugin functionality to firtool pipeline to dynamically load pass plugins and execute passes. `*.so` file is load with`--load-pass-plugin` option. Currently we can insert passes to 4 places in the pipeline: (1) after FIRRTL parsing (2) before LowerToHW (3) after HW lowering (4) after SV lowering.
This commit is contained in:
parent
aefe8280c3
commit
2f4af25eac
|
@ -18,7 +18,9 @@ set_property(GLOBAL PROPERTY CIRCT_CONVERSION_LIBS "@CIRCT_CONVERSION_LIBS@")
|
|||
set_property(GLOBAL PROPERTY CIRCT_TRANSLATION_LIBS "@CIRCT_TRANSLATION_LIBS@")
|
||||
|
||||
# Provide all our library targets to users.
|
||||
@CIRCT_CONFIG_INCLUDE_EXPORTS@
|
||||
if(NOT TARGET CIRCTSupport)
|
||||
@CIRCT_CONFIG_INCLUDE_EXPORTS@
|
||||
endif()
|
||||
|
||||
# By creating these targets here, subprojects that depend on CIRCT's
|
||||
# tablegen-generated headers can always depend on these targets whether building
|
||||
|
|
|
@ -4,6 +4,9 @@ set(LLVM_LINK_COMPONENTS
|
|||
|
||||
add_circt_tool(firtool
|
||||
firtool.cpp
|
||||
|
||||
DEPENDS
|
||||
SUPPORT_PLUGINS
|
||||
)
|
||||
llvm_update_compile_flags(firtool)
|
||||
target_link_libraries(firtool PRIVATE
|
||||
|
@ -27,3 +30,5 @@ target_link_libraries(firtool PRIVATE
|
|||
MLIRFuncDialect
|
||||
MLIRTransforms
|
||||
)
|
||||
|
||||
export_executable_symbols_for_plugins(firtool)
|
||||
|
|
|
@ -46,9 +46,11 @@
|
|||
#include "mlir/Pass/Pass.h"
|
||||
#include "mlir/Pass/PassInstrumentation.h"
|
||||
#include "mlir/Pass/PassManager.h"
|
||||
#include "mlir/Pass/PassRegistry.h"
|
||||
#include "mlir/Support/FileUtilities.h"
|
||||
#include "mlir/Support/Timing.h"
|
||||
#include "mlir/Support/ToolUtilities.h"
|
||||
#include "mlir/Tools/Plugins/PassPlugin.h"
|
||||
#include "mlir/Transforms/Passes.h"
|
||||
#include "llvm/Support/Chrono.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
|
@ -129,6 +131,34 @@ static cl::opt<bool>
|
|||
|
||||
static firtool::FirtoolOptions firtoolOptions(mainCategory);
|
||||
|
||||
static cl::list<std::string>
|
||||
passPlugins("load-pass-plugin", cl::desc("Load passes from plugin library"),
|
||||
cl::CommaSeparated, cl::cat(mainCategory));
|
||||
|
||||
static cl::opt<std::string>
|
||||
highFIRRTLPassPlugin("high-firrtl-pass-plugin",
|
||||
cl::desc("Insert passes after parsing FIRRTL. Specify "
|
||||
"passes with MLIR textual format."),
|
||||
cl::init(""), cl::cat(mainCategory));
|
||||
|
||||
static cl::opt<std::string>
|
||||
lowFIRRTLPassPlugin("low-firrtl-pass-plugin",
|
||||
cl::desc("Insert passes before lowering to HW. Specify "
|
||||
"passes with MLIR textual format."),
|
||||
cl::init(""), cl::cat(mainCategory));
|
||||
|
||||
static cl::opt<std::string>
|
||||
hwPassPlugin("hw-pass-plugin",
|
||||
cl::desc("Insert passes after lowering to HW. Specify "
|
||||
"passes with MLIR textual format."),
|
||||
cl::init(""), cl::cat(mainCategory));
|
||||
|
||||
static cl::opt<std::string>
|
||||
svPassPlugin("sv-pass-plugin",
|
||||
cl::desc("Insert passes after lowering to SV. Specify "
|
||||
"passes with MLIR textual format."),
|
||||
cl::init(""), cl::cat(mainCategory));
|
||||
|
||||
enum OutputFormatKind {
|
||||
OutputParseOnly,
|
||||
OutputIRFir,
|
||||
|
@ -350,17 +380,31 @@ static LogicalResult processBuffer(
|
|||
return printOp(*module, (*outputFile)->os());
|
||||
}
|
||||
|
||||
if (!highFIRRTLPassPlugin.empty())
|
||||
if (failed(parsePassPipeline(StringRef(highFIRRTLPassPlugin), pm)))
|
||||
return failure();
|
||||
|
||||
if (failed(firtool::populateCHIRRTLToLowFIRRTL(pm, firtoolOptions, *module,
|
||||
inputFilename)))
|
||||
return failure();
|
||||
|
||||
if (!lowFIRRTLPassPlugin.empty())
|
||||
if (failed(parsePassPipeline(StringRef(lowFIRRTLPassPlugin), pm)))
|
||||
return failure();
|
||||
|
||||
// Lower if we are going to verilog or if lowering was specifically requested.
|
||||
if (outputFormat != OutputIRFir) {
|
||||
if (failed(firtool::populateLowFIRRTLToHW(pm, firtoolOptions)))
|
||||
return failure();
|
||||
if (!hwPassPlugin.empty())
|
||||
if (failed(parsePassPipeline(StringRef(hwPassPlugin), pm)))
|
||||
return failure();
|
||||
if (outputFormat != OutputIRHW)
|
||||
if (failed(firtool::populateHWToSV(pm, firtoolOptions)))
|
||||
return failure();
|
||||
if (!svPassPlugin.empty())
|
||||
if (failed(parsePassPipeline(StringRef(svPassPlugin), pm)))
|
||||
return failure();
|
||||
}
|
||||
|
||||
// If the user requested HGLDD debug info emission, enable Verilog location
|
||||
|
@ -612,6 +656,19 @@ int main(int argc, char **argv) {
|
|||
// MLIR options are added below.
|
||||
cl::HideUnrelatedOptions(mainCategory);
|
||||
|
||||
/// Set the callback to load a pass plugin.
|
||||
passPlugins.setCallback([&](const std::string &pluginPath) {
|
||||
llvm::errs() << "[firtool] load plugin " << pluginPath << '\n';
|
||||
auto plugin = PassPlugin::load(pluginPath);
|
||||
if (!plugin) {
|
||||
errs() << plugin.takeError() << '\n';
|
||||
errs() << "Failed to load passes from '" << pluginPath
|
||||
<< "'. Request ignored.\n";
|
||||
return;
|
||||
}
|
||||
plugin.get().registerPassRegistryCallbacks();
|
||||
});
|
||||
|
||||
// Register passes before parsing command-line options, so that they are
|
||||
// available for use with options like `--mlir-print-ir-before`.
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue