diff --git a/test/circt-synth/basic.mlir b/test/circt-synth/basic.mlir index 8b4a30642bd6..110a977e3f87 100644 --- a/test/circt-synth/basic.mlir +++ b/test/circt-synth/basic.mlir @@ -1,7 +1,23 @@ // RUN: circt-synth %s | FileCheck %s +// RUN: circt-synth %s --until-before aig-lowering | FileCheck %s --check-prefix=AIG +// AIG-LABEL: @and // 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 +hw.module @and(in %a: i2, in %b: i2, in %c: i2, out and: i2) { + %0 = comb.and %a, %b, %c : i2 + // AIG-NEXT: %[[AND_INV:.+]] = aig.and_inv %a, %b, %c : i2 + // AIG-NEXT: hw.output %[[AND_INV]] : i2 + // CHECK-DAG: %[[B_1:.+]] = comb.extract %b from 1 : (i2) -> i1 + // CHECK-DAG: %[[C_1:.+]] = comb.extract %c from 1 : (i2) -> i1 + // CHECK-DAG: %[[AND_INV_0:.+]] = aig.and_inv %0, %[[C_1]] : i1 + // CHECK-DAG: %[[B_0:.+]] = comb.extract %b from 0 : (i2) -> i1 + // CHECK-DAG: %[[C_0:.+]] = comb.extract %c from 0 : (i2) -> i1 + // CHECK-DAG: %[[AND_INV_1:.+]] = aig.and_inv %[[B_0]], %[[C_0]] : i1 + // CHECK-DAG: %[[A_1:.+]] = comb.extract %a from 1 : (i2) -> i1 + // CHECK-DAG: %[[AND_INV_2:.+]] = aig.and_inv %[[A_1]], %[[AND_INV_0]] : i1 + // CHECK-DAG: %[[A_0:.+]] = comb.extract %a from 0 : (i2) -> i1 + // CHECK-DAG: %[[AND_INV_3:.+]] = aig.and_inv %[[A_0]], %[[AND_INV_1]] : i1 + // CHECK-DAG: %[[CONCAT:.+]] = comb.concat %[[AND_INV_2]], %[[AND_INV_3]] : i1, i1 + // CHECK-NEXT: hw.output %[[CONCAT]] : i2 + hw.output %0 : i2 } diff --git a/tools/circt-synth/CMakeLists.txt b/tools/circt-synth/CMakeLists.txt index 6efbd3acefa0..9b0b4b79b81b 100644 --- a/tools/circt-synth/CMakeLists.txt +++ b/tools/circt-synth/CMakeLists.txt @@ -2,7 +2,9 @@ add_circt_tool(circt-synth circt-synth.cpp) target_link_libraries(circt-synth PRIVATE CIRCTAIG + CIRCTAIGTransforms CIRCTComb + CIRCTCombToAIG CIRCTHW CIRCTSupport MLIRIR diff --git a/tools/circt-synth/circt-synth.cpp b/tools/circt-synth/circt-synth.cpp index f35c32cc0e0d..b54c7f90dd92 100644 --- a/tools/circt-synth/circt-synth.cpp +++ b/tools/circt-synth/circt-synth.cpp @@ -11,6 +11,7 @@ /// //===----------------------------------------------------------------------===// +#include "circt/Conversion/CombToAIG.h" #include "circt/Dialect/AIG/AIGDialect.h" #include "circt/Dialect/AIG/AIGPasses.h" #include "circt/Dialect/Comb/CombDialect.h" @@ -62,11 +63,53 @@ static cl::opt cl::desc("Log executions of toplevel module passes"), cl::init(false), cl::cat(mainCategory)); +// Options to control early-out from pipeline. +enum Until { UntilAIGLowering, UntilEnd }; + +static auto runUntilValues = llvm::cl::values( + clEnumValN(UntilAIGLowering, "aig-lowering", "Lowering of AIG"), + clEnumValN(UntilEnd, "all", "Run entire pipeline (default)")); + +static llvm::cl::opt runUntilBefore( + "until-before", llvm::cl::desc("Stop pipeline before a specified point"), + runUntilValues, llvm::cl::init(UntilEnd), llvm::cl::cat(mainCategory)); +static llvm::cl::opt runUntilAfter( + "until-after", llvm::cl::desc("Stop pipeline after a specified point"), + runUntilValues, llvm::cl::init(UntilEnd), llvm::cl::cat(mainCategory)); + +//===----------------------------------------------------------------------===// +// Main Tool Logic +//===----------------------------------------------------------------------===// + +static bool untilReached(Until until) { + return until >= runUntilBefore || until > runUntilAfter; +} + //===----------------------------------------------------------------------===// // Tool implementation //===----------------------------------------------------------------------===// -static void populateSynthesisPipeline(PassManager &pm) {} +static void populateSynthesisPipeline(PassManager &pm) { + auto &mpm = pm.nest(); + mpm.addPass(circt::createConvertCombToAIG()); + mpm.addPass(createCSEPass()); + if (untilReached(UntilAIGLowering)) + return; + mpm.addPass(createSimpleCanonicalizerPass()); + mpm.addPass(createCSEPass()); + mpm.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. + mpm.addPass(aig::createLowerWordToBits()); + mpm.addPass(createCSEPass()); + mpm.addPass(createSimpleCanonicalizerPass()); + // TODO: Add balancing, rewriting, FRAIG conversion, etc. + if (untilReached(UntilEnd)) + return; + + // TODO: Add LUT mapping, etc. +} /// This function initializes the various components of the tool and /// orchestrates the work to be done.