[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:
Hideto Ueno 2023-10-10 00:06:47 +09:00 committed by GitHub
parent aefe8280c3
commit 2f4af25eac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 65 additions and 1 deletions

View File

@ -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

View File

@ -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)

View File

@ -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`.
{