mirror of https://github.com/llvm/circt.git
[circt-synth] [Synthesis] Add synthesis pipeline and refactor the lib structure (#8681)
This commit introduces a standardized synthesis pipeline and restructures the codebase: * Creates a new SynthesisPipeline class to define the default synthesis pipeline. This pipeline serves both circt-synth and is exposed through the C API for Python bindings. * Added a dedicated Synthesis directory under `lib/` to house synthesis-related code. This architectural change is aimed to promote synthesis capabilities to a first-class component within CIRCT rather than limiting it to the circt-synth tool.
This commit is contained in:
parent
dd7b402d96
commit
1fb38a58ea
|
@ -0,0 +1,24 @@
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef CIRCT_C_SYNTHESIS_H
|
||||||
|
#define CIRCT_C_SYNTHESIS_H
|
||||||
|
|
||||||
|
#include "mlir-c/IR.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MLIR_CAPI_EXPORTED void registerSynthesisPipeline(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // CIRCT_C_SYNTHESIS_H
|
|
@ -0,0 +1,58 @@
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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 defines the default synthesis pipeline.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LIB_SYNTHESIS_SYNTHESISPIPELINE_H
|
||||||
|
#define LIB_SYNTHESIS_SYNTHESISPIPELINE_H
|
||||||
|
|
||||||
|
#include "circt-c/Synthesis.h"
|
||||||
|
#include "mlir/Pass/PassManager.h"
|
||||||
|
#include "mlir/Pass/PassOptions.h"
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Pipeline Options
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
namespace circt {
|
||||||
|
namespace synthesis {
|
||||||
|
|
||||||
|
/// Options for the aig optimization pipeline.
|
||||||
|
struct AIGOptimizationPipelineOptions
|
||||||
|
: public mlir::PassPipelineOptions<AIGOptimizationPipelineOptions> {
|
||||||
|
PassOptions::ListOption<std::string> abcCommands{
|
||||||
|
*this, "abc-commands", llvm::cl::desc("ABC passes to run")};
|
||||||
|
|
||||||
|
PassOptions::Option<std::string> abcPath{
|
||||||
|
*this, "abc-path", llvm::cl::desc("Path to ABC"), llvm::cl::init("abc")};
|
||||||
|
|
||||||
|
PassOptions::Option<bool> ignoreAbcFailures{
|
||||||
|
*this, "ignore-abc-failures",
|
||||||
|
llvm::cl::desc("Continue on ABC failure instead of aborting"),
|
||||||
|
llvm::cl::init(false)};
|
||||||
|
};
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Pipeline Functions
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
/// Populate the synthesis pipelines.
|
||||||
|
void buildAIGLoweringPipeline(mlir::OpPassManager &pm);
|
||||||
|
void buildAIGOptimizationPipeline(
|
||||||
|
mlir::OpPassManager &pm, const AIGOptimizationPipelineOptions &options);
|
||||||
|
|
||||||
|
/// Register the synthesis pipelines.
|
||||||
|
void registerSynthesisPipeline();
|
||||||
|
|
||||||
|
} // namespace synthesis
|
||||||
|
} // namespace circt
|
||||||
|
|
||||||
|
#endif // LIB_SYNTHESIS_SYNTHESISPIPELINE_H
|
|
@ -0,0 +1,36 @@
|
||||||
|
# REQUIRES: bindings_python
|
||||||
|
# RUN: %PYTHON% %s | FileCheck %s
|
||||||
|
|
||||||
|
import circt
|
||||||
|
from circt.dialects import hw, comb
|
||||||
|
from circt.ir import Context, Location, Module, InsertionPoint, IntegerType
|
||||||
|
from circt.passmanager import PassManager
|
||||||
|
|
||||||
|
with Context() as ctx, Location.unknown():
|
||||||
|
circt.register_dialects(ctx)
|
||||||
|
|
||||||
|
m = Module.create()
|
||||||
|
with InsertionPoint(m.body):
|
||||||
|
i4 = IntegerType.get_signless(4)
|
||||||
|
|
||||||
|
# Create a module with comb.mul
|
||||||
|
def build_module(module):
|
||||||
|
a, b = module.entry_block.arguments
|
||||||
|
hw.OutputOp([comb.mul([a, b])])
|
||||||
|
|
||||||
|
hw.HWModuleOp(
|
||||||
|
name="foo",
|
||||||
|
input_ports=[("a", i4), ("b", i4)],
|
||||||
|
output_ports=[("out", i4)],
|
||||||
|
body_builder=build_module,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check that the synthesis pipeline is registered.
|
||||||
|
pm = PassManager.parse(
|
||||||
|
"builtin.module(hw.module(synthesis-aig-lowering-pipeline, "
|
||||||
|
"synthesis-aig-optimization-pipeline))")
|
||||||
|
pm.run(m.operation)
|
||||||
|
# CHECK: hw.module @foo(
|
||||||
|
# CHECK-NOT: comb.mul
|
||||||
|
# CHECK: aig.and_inv
|
||||||
|
print(m.operation)
|
|
@ -26,6 +26,7 @@
|
||||||
#include "circt-c/Dialect/OM.h"
|
#include "circt-c/Dialect/OM.h"
|
||||||
#include "circt-c/Dialect/Pipeline.h"
|
#include "circt-c/Dialect/Pipeline.h"
|
||||||
#include "circt-c/Dialect/RTG.h"
|
#include "circt-c/Dialect/RTG.h"
|
||||||
|
#include "circt-c/Synthesis.h"
|
||||||
#include "circt-c/Transforms.h"
|
#include "circt-c/Transforms.h"
|
||||||
#ifdef CIRCT_INCLUDE_TESTS
|
#ifdef CIRCT_INCLUDE_TESTS
|
||||||
#include "circt-c/Dialect/RTGTest.h"
|
#include "circt-c/Dialect/RTGTest.h"
|
||||||
|
@ -63,6 +64,7 @@ static void registerPasses() {
|
||||||
registerHandshakePasses();
|
registerHandshakePasses();
|
||||||
registerKanagawaPasses();
|
registerKanagawaPasses();
|
||||||
registerPipelinePasses();
|
registerPipelinePasses();
|
||||||
|
registerSynthesisPipeline();
|
||||||
mlirRegisterCIRCTConversionPasses();
|
mlirRegisterCIRCTConversionPasses();
|
||||||
mlirRegisterCIRCTTransformsPasses();
|
mlirRegisterCIRCTTransformsPasses();
|
||||||
mlirRegisterTransformsCSE();
|
mlirRegisterTransformsCSE();
|
||||||
|
|
|
@ -55,6 +55,7 @@ set(PYTHON_BINDINGS_LINK_LIBS
|
||||||
CIRCTCAPISV
|
CIRCTCAPISV
|
||||||
CIRCTCAPIVerif
|
CIRCTCAPIVerif
|
||||||
CIRCTCAPITransforms
|
CIRCTCAPITransforms
|
||||||
|
CIRCTCAPISynthesis
|
||||||
MLIRCAPIIndex
|
MLIRCAPIIndex
|
||||||
MLIRCAPISMT
|
MLIRCAPISMT
|
||||||
MLIRCAPIExportSMTLIB
|
MLIRCAPIExportSMTLIB
|
||||||
|
|
|
@ -4,4 +4,5 @@ add_subdirectory(ExportVerilog)
|
||||||
add_subdirectory(Dialect)
|
add_subdirectory(Dialect)
|
||||||
add_subdirectory(Firtool)
|
add_subdirectory(Firtool)
|
||||||
add_subdirectory(RtgTool)
|
add_subdirectory(RtgTool)
|
||||||
|
add_subdirectory(Synthesis)
|
||||||
add_subdirectory(Transforms)
|
add_subdirectory(Transforms)
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
add_circt_public_c_api_library(CIRCTCAPISynthesis
|
||||||
|
SynthesisPipeline.cpp
|
||||||
|
|
||||||
|
LINK_LIBS PUBLIC
|
||||||
|
CIRCTSynthesis
|
||||||
|
MLIRCAPIIR
|
||||||
|
)
|
|
@ -0,0 +1,15 @@
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "circt-c/Synthesis.h"
|
||||||
|
|
||||||
|
#include "circt/Synthesis/SynthesisPipeline.h"
|
||||||
|
|
||||||
|
void registerSynthesisPipeline() {
|
||||||
|
circt::synthesis::registerSynthesisPipeline();
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ add_subdirectory(Firtool)
|
||||||
add_subdirectory(Reduce)
|
add_subdirectory(Reduce)
|
||||||
add_subdirectory(Scheduling)
|
add_subdirectory(Scheduling)
|
||||||
add_subdirectory(Support)
|
add_subdirectory(Support)
|
||||||
|
add_subdirectory(Synthesis)
|
||||||
add_subdirectory(Target)
|
add_subdirectory(Target)
|
||||||
add_subdirectory(Tools)
|
add_subdirectory(Tools)
|
||||||
add_subdirectory(Transforms)
|
add_subdirectory(Transforms)
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
add_circt_library(CIRCTSynthesis
|
||||||
|
SynthesisPipeline.cpp
|
||||||
|
|
||||||
|
LINK_LIBS PUBLIC
|
||||||
|
CIRCTAIGTransforms
|
||||||
|
CIRCTCombToAIG
|
||||||
|
CIRCTHWTransforms
|
||||||
|
CIRCTSupport
|
||||||
|
|
||||||
|
MLIRIR
|
||||||
|
MLIRSupport
|
||||||
|
MLIRTransforms
|
||||||
|
)
|
|
@ -0,0 +1,95 @@
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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 implements the default synthesis pipeline from core dialect to AIG.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "circt/Synthesis/SynthesisPipeline.h"
|
||||||
|
#include "circt/Conversion/CombToAIG.h"
|
||||||
|
#include "circt/Dialect/AIG/AIGPasses.h"
|
||||||
|
#include "circt/Dialect/Comb/CombOps.h"
|
||||||
|
#include "circt/Dialect/HW/HWOps.h"
|
||||||
|
#include "circt/Dialect/HW/HWPasses.h"
|
||||||
|
#include "circt/Support/Passes.h"
|
||||||
|
#include "circt/Transforms/Passes.h"
|
||||||
|
#include "mlir/Pass/PassManager.h"
|
||||||
|
#include "mlir/Transforms/Passes.h"
|
||||||
|
#include "llvm/ADT/SmallVector.h"
|
||||||
|
|
||||||
|
using namespace mlir;
|
||||||
|
using namespace circt;
|
||||||
|
using namespace circt::synthesis;
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Pipeline Implementation
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
/// Helper function to populate additional legal ops for partial legalization.
|
||||||
|
template <typename... AllowedOpTy>
|
||||||
|
static void partiallyLegalizeCombToAIG(SmallVectorImpl<std::string> &ops) {
|
||||||
|
(ops.push_back(AllowedOpTy::getOperationName().str()), ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
void circt::synthesis::buildAIGLoweringPipeline(OpPassManager &pm) {
|
||||||
|
{
|
||||||
|
// Partially legalize Comb to AIG, run CSE and canonicalization.
|
||||||
|
circt::ConvertCombToAIGOptions convOptions;
|
||||||
|
partiallyLegalizeCombToAIG<comb::AndOp, comb::OrOp, comb::XorOp,
|
||||||
|
comb::MuxOp, comb::ICmpOp, hw::ArrayGetOp,
|
||||||
|
hw::ArraySliceOp, hw::ArrayCreateOp,
|
||||||
|
hw::ArrayConcatOp, hw::AggregateConstantOp>(
|
||||||
|
convOptions.additionalLegalOps);
|
||||||
|
pm.addPass(circt::createConvertCombToAIG(convOptions));
|
||||||
|
}
|
||||||
|
pm.addPass(createCSEPass());
|
||||||
|
pm.addPass(createSimpleCanonicalizerPass());
|
||||||
|
|
||||||
|
pm.addPass(circt::hw::createHWAggregateToCombPass());
|
||||||
|
pm.addPass(circt::createConvertCombToAIG());
|
||||||
|
pm.addPass(createCSEPass());
|
||||||
|
pm.addPass(createSimpleCanonicalizerPass());
|
||||||
|
pm.addPass(createCSEPass());
|
||||||
|
}
|
||||||
|
|
||||||
|
void circt::synthesis::buildAIGOptimizationPipeline(
|
||||||
|
OpPassManager &pm, const AIGOptimizationPipelineOptions &options) {
|
||||||
|
|
||||||
|
pm.addPass(aig::createLowerVariadic());
|
||||||
|
|
||||||
|
// TODO: LowerWordToBits is not scalable for large designs. Change to
|
||||||
|
// conditionally enable the pass once the rest of the pipeline was able
|
||||||
|
// to handle multibit operands properly.
|
||||||
|
pm.addPass(aig::createLowerWordToBits());
|
||||||
|
pm.addPass(createCSEPass());
|
||||||
|
pm.addPass(createSimpleCanonicalizerPass());
|
||||||
|
|
||||||
|
if (!options.abcCommands.empty()) {
|
||||||
|
aig::ABCRunnerOptions abcOptions;
|
||||||
|
abcOptions.abcPath = options.abcPath;
|
||||||
|
abcOptions.abcCommands.assign(options.abcCommands.begin(),
|
||||||
|
options.abcCommands.end());
|
||||||
|
abcOptions.continueOnFailure = options.ignoreAbcFailures;
|
||||||
|
pm.addPass(aig::createABCRunner(abcOptions));
|
||||||
|
}
|
||||||
|
// TODO: Add balancing, rewriting, FRAIG conversion, etc.
|
||||||
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Pipeline Registration
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
void circt::synthesis::registerSynthesisPipeline() {
|
||||||
|
PassPipelineRegistration<EmptyPipelineOptions>(
|
||||||
|
"synthesis-aig-lowering-pipeline",
|
||||||
|
"The default pipeline for until AIG lowering", buildAIGLoweringPipeline);
|
||||||
|
PassPipelineRegistration<AIGOptimizationPipelineOptions>(
|
||||||
|
"synthesis-aig-optimization-pipeline",
|
||||||
|
"The default pipeline for AIG optimization pipeline",
|
||||||
|
buildAIGOptimizationPipeline);
|
||||||
|
}
|
|
@ -3,20 +3,17 @@ target_link_libraries(circt-synth
|
||||||
PRIVATE
|
PRIVATE
|
||||||
CIRCTAIG
|
CIRCTAIG
|
||||||
CIRCTAIGToComb
|
CIRCTAIGToComb
|
||||||
CIRCTAIGTransforms
|
|
||||||
CIRCTAIGAnalysis
|
CIRCTAIGAnalysis
|
||||||
CIRCTComb
|
CIRCTComb
|
||||||
CIRCTCombToAIG
|
|
||||||
CIRCTDebug
|
CIRCTDebug
|
||||||
CIRCTEmit
|
CIRCTEmit
|
||||||
CIRCTHW
|
CIRCTHW
|
||||||
CIRCTHWTransforms
|
|
||||||
CIRCTLTL
|
CIRCTLTL
|
||||||
CIRCTOM
|
CIRCTOM
|
||||||
CIRCTSeq
|
CIRCTSeq
|
||||||
CIRCTSim
|
CIRCTSim
|
||||||
CIRCTSupport
|
|
||||||
CIRCTSV
|
CIRCTSV
|
||||||
|
CIRCTSynthesis
|
||||||
CIRCTTransforms
|
CIRCTTransforms
|
||||||
CIRCTVerif
|
CIRCTVerif
|
||||||
MLIRBytecodeWriter
|
MLIRBytecodeWriter
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "circt/Conversion/AIGToComb.h"
|
#include "circt/Conversion/AIGToComb.h"
|
||||||
#include "circt/Conversion/CombToAIG.h"
|
|
||||||
#include "circt/Dialect/AIG/AIGDialect.h"
|
#include "circt/Dialect/AIG/AIGDialect.h"
|
||||||
#include "circt/Dialect/AIG/AIGPasses.h"
|
#include "circt/Dialect/AIG/AIGPasses.h"
|
||||||
#include "circt/Dialect/AIG/Analysis/LongestPathAnalysis.h"
|
#include "circt/Dialect/AIG/Analysis/LongestPathAnalysis.h"
|
||||||
|
@ -22,7 +21,6 @@
|
||||||
#include "circt/Dialect/Emit/EmitDialect.h"
|
#include "circt/Dialect/Emit/EmitDialect.h"
|
||||||
#include "circt/Dialect/HW/HWDialect.h"
|
#include "circt/Dialect/HW/HWDialect.h"
|
||||||
#include "circt/Dialect/HW/HWOps.h"
|
#include "circt/Dialect/HW/HWOps.h"
|
||||||
#include "circt/Dialect/HW/HWPasses.h"
|
|
||||||
#include "circt/Dialect/LTL/LTLDialect.h"
|
#include "circt/Dialect/LTL/LTLDialect.h"
|
||||||
#include "circt/Dialect/OM/OMDialect.h"
|
#include "circt/Dialect/OM/OMDialect.h"
|
||||||
#include "circt/Dialect/SV/SVDialect.h"
|
#include "circt/Dialect/SV/SVDialect.h"
|
||||||
|
@ -31,12 +29,14 @@
|
||||||
#include "circt/Dialect/Verif/VerifDialect.h"
|
#include "circt/Dialect/Verif/VerifDialect.h"
|
||||||
#include "circt/Support/Passes.h"
|
#include "circt/Support/Passes.h"
|
||||||
#include "circt/Support/Version.h"
|
#include "circt/Support/Version.h"
|
||||||
|
#include "circt/Synthesis/SynthesisPipeline.h"
|
||||||
#include "circt/Transforms/Passes.h"
|
#include "circt/Transforms/Passes.h"
|
||||||
#include "mlir/Bytecode/BytecodeWriter.h"
|
#include "mlir/Bytecode/BytecodeWriter.h"
|
||||||
#include "mlir/IR/Diagnostics.h"
|
#include "mlir/IR/Diagnostics.h"
|
||||||
#include "mlir/IR/OwningOpRef.h"
|
#include "mlir/IR/OwningOpRef.h"
|
||||||
#include "mlir/Parser/Parser.h"
|
#include "mlir/Parser/Parser.h"
|
||||||
#include "mlir/Pass/PassManager.h"
|
#include "mlir/Pass/PassManager.h"
|
||||||
|
#include "mlir/Pass/PassRegistry.h"
|
||||||
#include "mlir/Support/FileUtilities.h"
|
#include "mlir/Support/FileUtilities.h"
|
||||||
#include "mlir/Support/LogicalResult.h"
|
#include "mlir/Support/LogicalResult.h"
|
||||||
#include "mlir/Transforms/Passes.h"
|
#include "mlir/Transforms/Passes.h"
|
||||||
|
@ -51,6 +51,7 @@ namespace cl = llvm::cl;
|
||||||
|
|
||||||
using namespace mlir;
|
using namespace mlir;
|
||||||
using namespace circt;
|
using namespace circt;
|
||||||
|
using namespace synthesis;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Command-line options declaration
|
// Command-line options declaration
|
||||||
|
@ -90,7 +91,6 @@ static cl::opt<bool>
|
||||||
cl::desc("Allow unknown dialects in the input"),
|
cl::desc("Allow unknown dialects in the input"),
|
||||||
cl::init(false), cl::cat(mainCategory));
|
cl::init(false), cl::cat(mainCategory));
|
||||||
|
|
||||||
// Options to control early-out from pipeline.
|
|
||||||
enum Until { UntilAIGLowering, UntilEnd };
|
enum Until { UntilAIGLowering, UntilEnd };
|
||||||
|
|
||||||
static auto runUntilValues = llvm::cl::values(
|
static auto runUntilValues = llvm::cl::values(
|
||||||
|
@ -140,7 +140,7 @@ static cl::opt<std::string> abcPath("abc-path", cl::desc("Path to ABC"),
|
||||||
cl::cat(mainCategory));
|
cl::cat(mainCategory));
|
||||||
|
|
||||||
static cl::opt<bool>
|
static cl::opt<bool>
|
||||||
continueOnFailure("ignore-abc-failures",
|
ignoreAbcFailures("ignore-abc-failures",
|
||||||
cl::desc("Continue on ABC failure instead of aborting"),
|
cl::desc("Continue on ABC failure instead of aborting"),
|
||||||
cl::init(false), cl::cat(mainCategory));
|
cl::init(false), cl::cat(mainCategory));
|
||||||
|
|
||||||
|
@ -152,6 +152,17 @@ static bool untilReached(Until until) {
|
||||||
return until >= runUntilBefore || until > runUntilAfter;
|
return until >= runUntilBefore || until > runUntilAfter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nestOrAddToHierarchicalRunner(OpPassManager &pm,
|
||||||
|
std::function<void(OpPassManager &pm)> pipeline,
|
||||||
|
const std::string &topName) {
|
||||||
|
if (topName.empty()) {
|
||||||
|
pipeline(pm.nest<hw::HWModuleOp>());
|
||||||
|
} else {
|
||||||
|
pm.addPass(circt::createHierarchicalRunner(topName, pipeline));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Tool implementation
|
// Tool implementation
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -161,60 +172,24 @@ static void partiallyLegalizeCombToAIG(SmallVectorImpl<std::string> &ops) {
|
||||||
(ops.push_back(AllowedOpTy::getOperationName().str()), ...);
|
(ops.push_back(AllowedOpTy::getOperationName().str()), ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void populateSynthesisPipeline(PassManager &pm) {
|
// Add a default synthesis pipeline and analysis.
|
||||||
auto pipeline = [](OpPassManager &mpm) {
|
static void populateCIRCTSynthPipeline(PassManager &pm) {
|
||||||
// Add the AIG to Comb at the scope exit if requested.
|
auto pipeline = [](OpPassManager &pm) {
|
||||||
auto addAIGToComb = llvm::make_scope_exit([&]() {
|
circt::synthesis::buildAIGLoweringPipeline(pm);
|
||||||
if (convertToComb) {
|
|
||||||
mpm.addPass(circt::createConvertAIGToComb());
|
|
||||||
mpm.addPass(createCSEPass());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
{
|
|
||||||
// Partially legalize Comb to AIG, run CSE and canonicalization.
|
|
||||||
circt::ConvertCombToAIGOptions options;
|
|
||||||
partiallyLegalizeCombToAIG<comb::AndOp, comb::OrOp, comb::XorOp,
|
|
||||||
comb::MuxOp, comb::ICmpOp, hw::ArrayGetOp,
|
|
||||||
hw::ArraySliceOp, hw::ArrayCreateOp,
|
|
||||||
hw::ArrayConcatOp, hw::AggregateConstantOp>(
|
|
||||||
options.additionalLegalOps);
|
|
||||||
mpm.addPass(circt::createConvertCombToAIG(options));
|
|
||||||
}
|
|
||||||
mpm.addPass(createCSEPass());
|
|
||||||
mpm.addPass(createSimpleCanonicalizerPass());
|
|
||||||
|
|
||||||
mpm.addPass(circt::hw::createHWAggregateToCombPass());
|
|
||||||
mpm.addPass(circt::createConvertCombToAIG());
|
|
||||||
mpm.addPass(createCSEPass());
|
|
||||||
if (untilReached(UntilAIGLowering))
|
if (untilReached(UntilAIGLowering))
|
||||||
return;
|
return;
|
||||||
mpm.addPass(createSimpleCanonicalizerPass());
|
|
||||||
mpm.addPass(createCSEPass());
|
circt::synthesis::AIGOptimizationPipelineOptions options;
|
||||||
mpm.addPass(aig::createLowerVariadic());
|
options.abcCommands = abcCommands;
|
||||||
// TODO: LowerWordToBits is not scalable for large designs. Change to
|
options.abcPath.setValue(abcPath);
|
||||||
// conditionally enable the pass once the rest of the pipeline was able
|
options.ignoreAbcFailures.setValue(ignoreAbcFailures);
|
||||||
// to handle multibit operands properly.
|
|
||||||
mpm.addPass(aig::createLowerWordToBits());
|
circt::synthesis::buildAIGOptimizationPipeline(pm, options);
|
||||||
mpm.addPass(createCSEPass());
|
|
||||||
mpm.addPass(createSimpleCanonicalizerPass());
|
|
||||||
if (!abcCommands.empty()) {
|
|
||||||
aig::ABCRunnerOptions options;
|
|
||||||
options.abcPath = abcPath;
|
|
||||||
options.abcCommands.assign(abcCommands.begin(), abcCommands.end());
|
|
||||||
options.continueOnFailure = continueOnFailure;
|
|
||||||
mpm.addPass(aig::createABCRunner(options));
|
|
||||||
}
|
|
||||||
// TODO: Add balancing, rewriting, FRAIG conversion, etc.
|
|
||||||
if (untilReached(UntilEnd))
|
|
||||||
return;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (topName.empty()) {
|
nestOrAddToHierarchicalRunner(pm, pipeline, topName);
|
||||||
pipeline(pm.nest<hw::HWModuleOp>());
|
|
||||||
} else {
|
|
||||||
pm.addPass(circt::createHierarchicalRunner(topName, pipeline));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Run analysis if requested.
|
||||||
if (!outputLongestPath.empty()) {
|
if (!outputLongestPath.empty()) {
|
||||||
circt::aig::PrintLongestPathAnalysisOptions options;
|
circt::aig::PrintLongestPathAnalysisOptions options;
|
||||||
options.outputFile = outputLongestPath;
|
options.outputFile = outputLongestPath;
|
||||||
|
@ -223,7 +198,14 @@ static void populateSynthesisPipeline(PassManager &pm) {
|
||||||
pm.addPass(circt::aig::createPrintLongestPathAnalysis(options));
|
pm.addPass(circt::aig::createPrintLongestPathAnalysis(options));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add LUT mapping, etc.
|
if (convertToComb)
|
||||||
|
nestOrAddToHierarchicalRunner(
|
||||||
|
pm,
|
||||||
|
[&](OpPassManager &pm) {
|
||||||
|
pm.addPass(circt::createConvertAIGToComb());
|
||||||
|
pm.addPass(createCSEPass());
|
||||||
|
},
|
||||||
|
topName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check output stream before writing bytecode to it.
|
/// Check output stream before writing bytecode to it.
|
||||||
|
@ -285,7 +267,7 @@ static LogicalResult executeSynthesis(MLIRContext &context) {
|
||||||
pm.addInstrumentation(
|
pm.addInstrumentation(
|
||||||
std::make_unique<VerbosePassInstrumentation<mlir::ModuleOp>>(
|
std::make_unique<VerbosePassInstrumentation<mlir::ModuleOp>>(
|
||||||
"circt-synth"));
|
"circt-synth"));
|
||||||
populateSynthesisPipeline(pm);
|
populateCIRCTSynthPipeline(pm);
|
||||||
|
|
||||||
if (!topName.empty()) {
|
if (!topName.empty()) {
|
||||||
// Set a top module name for the longest path analysis.
|
// Set a top module name for the longest path analysis.
|
||||||
|
@ -320,6 +302,7 @@ int main(int argc, char **argv) {
|
||||||
registerPassManagerCLOptions();
|
registerPassManagerCLOptions();
|
||||||
registerDefaultTimingManagerCLOptions();
|
registerDefaultTimingManagerCLOptions();
|
||||||
registerAsmPrinterCLOptions();
|
registerAsmPrinterCLOptions();
|
||||||
|
|
||||||
cl::AddExtraVersionPrinter(
|
cl::AddExtraVersionPrinter(
|
||||||
[](llvm::raw_ostream &os) { os << circt::getCirctVersion() << '\n'; });
|
[](llvm::raw_ostream &os) { os << circt::getCirctVersion() << '\n'; });
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue