[circt-synth] Add circt-synth driver

This adds a tool to perform synthesis on core dialect IR.
This commit is contained in:
Hideto Ueno 2024-10-26 03:15:34 +09:00
parent e937bb7f56
commit 7195bf3450
7 changed files with 187 additions and 2 deletions

View File

@ -26,6 +26,7 @@ set(CIRCT_TEST_DEPENDS
circt-dis
circt-lec
circt-opt
circt-synth
circt-test
circt-translate
circt-reduce

View File

@ -0,0 +1,7 @@
// RUN: circt-synth %s | FileCheck %s
// CHECK-LABEL: @and
hw.module @and(in %a: i1, in %b: i1, out and: i1) {
%0 = comb.and %a, %b : i1
hw.output %0 : i1
}

View File

@ -0,0 +1,3 @@
// RUN: circt-synth --help | FileCheck %s
// CHECK: OVERVIEW: Logic synthesis tool

View File

@ -60,8 +60,8 @@ tool_dirs = [
tools = [
'arcilator', 'circt-as', 'circt-capi-ir-test', 'circt-capi-om-test',
'circt-capi-firrtl-test', 'circt-capi-firtool-test', 'circt-dis',
'circt-lec', 'circt-reduce', 'circt-test', 'circt-translate', 'firtool',
'hlstool', 'om-linker', 'ibistool'
'circt-lec', 'circt-reduce', 'circt-synth', 'circt-test', 'circt-translate',
'firtool', 'hlstool', 'om-linker', 'ibistool'
]
if "CIRCT_OPT_CHECK_IR_ROUNDTRIP" in os.environ:

View File

@ -8,6 +8,7 @@ add_subdirectory(circt-lsp-server)
add_subdirectory(circt-opt)
add_subdirectory(circt-reduce)
add_subdirectory(circt-rtl-sim)
add_subdirectory(circt-synth)
add_subdirectory(circt-test)
add_subdirectory(circt-translate)
add_subdirectory(firtool)

View File

@ -0,0 +1,14 @@
add_circt_tool(circt-synth circt-synth.cpp)
target_link_libraries(circt-synth
PRIVATE
CIRCTAIG
CIRCTComb
CIRCTHW
CIRCTSupport
MLIRIR
MLIRParser
LLVMSupport
)
llvm_update_compile_flags(circt-synth)
mlir_check_all_link_libraries(circt-synth)

View File

@ -0,0 +1,159 @@
//===- circt-synth.cpp - The circt-synth driver -----------------*- 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
//
//===----------------------------------------------------------------------===//
///
/// This file initializes the 'circt-synth' tool, which performs logic
/// synthesis.
///
//===----------------------------------------------------------------------===//
#include "circt/Dialect/AIG/AIGDialect.h"
#include "circt/Dialect/AIG/AIGPasses.h"
#include "circt/Dialect/Comb/CombDialect.h"
#include "circt/Dialect/HW/HWDialect.h"
#include "circt/Dialect/HW/HWOps.h"
#include "circt/Support/Passes.h"
#include "circt/Support/Version.h"
#include "mlir/IR/Diagnostics.h"
#include "mlir/IR/OwningOpRef.h"
#include "mlir/Parser/Parser.h"
#include "mlir/Pass/PassManager.h"
#include "mlir/Support/FileUtilities.h"
#include "mlir/Support/LogicalResult.h"
#include "mlir/Transforms/Passes.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/ToolOutputFile.h"
namespace cl = llvm::cl;
using namespace mlir;
using namespace circt;
//===----------------------------------------------------------------------===//
// Command-line options declaration
//===----------------------------------------------------------------------===//
static cl::OptionCategory mainCategory("circt-synth Options");
static cl::opt<std::string> inputFilename(cl::Positional, cl::init("-"),
cl::desc("Specify an input file"),
cl::value_desc("filename"),
cl::cat(mainCategory));
static cl::opt<std::string> outputFilename("o", cl::desc("Output filename"),
cl::value_desc("filename"),
cl::init("-"),
cl::cat(mainCategory));
static cl::opt<bool>
verifyPasses("verify-each",
cl::desc("Run the verifier after each transformation pass"),
cl::init(true), cl::cat(mainCategory));
static cl::opt<bool>
verbosePassExecutions("verbose-pass-executions",
cl::desc("Log executions of toplevel module passes"),
cl::init(false), cl::cat(mainCategory));
//===----------------------------------------------------------------------===//
// Tool implementation
//===----------------------------------------------------------------------===//
static void populateSynthesisPipeline(PassManager &pm) {}
/// This function initializes the various components of the tool and
/// orchestrates the work to be done.
static LogicalResult executeSynthesis(MLIRContext &context) {
// Create the timing manager we use to sample execution times.
DefaultTimingManager tm;
applyDefaultTimingManagerCLOptions(tm);
auto ts = tm.getRootScope();
OwningOpRef<ModuleOp> module;
{
auto parserTimer = ts.nest("Parse MLIR input");
// Parse the provided input files.
module = parseSourceFile<ModuleOp>(inputFilename, &context);
}
if (!module)
return failure();
// Create the output directory or output file depending on our mode.
std::optional<std::unique_ptr<llvm::ToolOutputFile>> outputFile;
std::string errorMessage;
// Create an output file.
outputFile.emplace(openOutputFile(outputFilename, &errorMessage));
if (!outputFile.value()) {
llvm::errs() << errorMessage << "\n";
return failure();
}
PassManager pm(&context);
pm.enableVerifier(verifyPasses);
pm.enableTiming(ts);
if (failed(applyPassManagerCLOptions(pm)))
return failure();
if (verbosePassExecutions)
pm.addInstrumentation(
std::make_unique<VerbosePassInstrumentation<mlir::ModuleOp>>(
"circt-synth"));
populateSynthesisPipeline(pm);
if (failed(pm.run(module.get())))
return failure();
auto timer = ts.nest("Print MLIR output");
OpPrintingFlags printingFlags;
module->print(outputFile.value()->os(), printingFlags);
outputFile.value()->keep();
return success();
}
/// The entry point for the `circt-synth` tool:
/// configures and parses the command-line options,
/// registers all dialects within a MLIR context,
/// and calls the `executeSynthesis` function to do the actual work.
int main(int argc, char **argv) {
llvm::InitLLVM y(argc, argv);
// Hide default LLVM options, other than for this tool.
// MLIR options are added below.
cl::HideUnrelatedOptions(mainCategory);
// Register any pass manager command line options.
registerMLIRContextCLOptions();
registerPassManagerCLOptions();
registerDefaultTimingManagerCLOptions();
registerAsmPrinterCLOptions();
cl::AddExtraVersionPrinter(
[](llvm::raw_ostream &os) { os << circt::getCirctVersion() << '\n'; });
// Parse the command-line options provided by the user.
cl::ParseCommandLineOptions(argc, argv, "Logic synthesis tool\n\n");
// Set the bug report message to indicate users should file issues on
// llvm/circt and not llvm/llvm-project.
llvm::setBugReportMsg(circt::circtBugReportMsg);
// Register the supported CIRCT dialects and create a context to work with.
DialectRegistry registry;
registry.insert<circt::aig::AIGDialect, circt::comb::CombDialect,
circt::hw::HWDialect>();
MLIRContext context(registry);
// Setup of diagnostic handling.
llvm::SourceMgr sourceMgr;
SourceMgrDiagnosticHandler sourceMgrHandler(sourceMgr, &context);
// Avoid printing a superfluous note on diagnostic emission.
context.printOpOnDiagnostic(false);
// Perform the synthesis; using `exit` to avoid the slow
// teardown of the MLIR context.
exit(failed(executeSynthesis(context)));
}