-
Notifications
You must be signed in to change notification settings - Fork 302
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[CombToAIG] Add CombToAIG conversion pass (#7740)
This adds a conversion pass from Comb to AIG. Currently conversion patterns for variadic `comb.or/and` and binary xor are supported. There will be a follow up to implement conversion patterns for arithmetic ops.
- Loading branch information
Showing
8 changed files
with
194 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
//===- CombToAIG.h - Comb to AIG dialect conversion -------------*- 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef CIRCT_CONVERSION_COMBTOAIG_H | ||
#define CIRCT_CONVERSION_COMBTOAIG_H | ||
|
||
#include "circt/Support/LLVM.h" | ||
#include <memory> | ||
|
||
namespace circt { | ||
|
||
#define GEN_PASS_DECL_CONVERTCOMBTOAIG | ||
#include "circt/Conversion/Passes.h.inc" | ||
|
||
} // namespace circt | ||
|
||
#endif // CIRCT_CONVERSION_COMBTOAIG_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
add_circt_conversion_library(CIRCTCombToAIG | ||
CombToAIG.cpp | ||
|
||
ADDITIONAL_HEADER_DIRS | ||
${CIRCT_MAIN_INCLUDE_DIR}/circt/Conversion/CombToAIG | ||
|
||
DEPENDS | ||
CIRCTConversionPassIncGen | ||
|
||
LINK_LIBS PUBLIC | ||
CIRCTHW | ||
CIRCTComb | ||
CIRCTAIG | ||
MLIRIR | ||
MLIRPass | ||
MLIRSupport | ||
MLIRTransforms | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
//===- CombToAIG.cpp - Comb to AIG Conversion Pass --------------*- 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 is the main Comb to AIG Conversion Pass Implementation. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "circt/Conversion/CombToAIG.h" | ||
#include "circt/Dialect/AIG/AIGOps.h" | ||
#include "circt/Dialect/Comb/CombOps.h" | ||
#include "circt/Dialect/HW/HWOps.h" | ||
#include "mlir/Pass/Pass.h" | ||
#include "mlir/Transforms/DialectConversion.h" | ||
|
||
namespace circt { | ||
#define GEN_PASS_DEF_CONVERTCOMBTOAIG | ||
#include "circt/Conversion/Passes.h.inc" | ||
} // namespace circt | ||
|
||
using namespace circt; | ||
using namespace comb; | ||
|
||
//===----------------------------------------------------------------------===// | ||
// Conversion patterns | ||
//===----------------------------------------------------------------------===// | ||
|
||
namespace { | ||
|
||
/// Lower a comb::AndOp operation to aig::AndInverterOp | ||
struct CombAndOpConversion : OpConversionPattern<AndOp> { | ||
using OpConversionPattern<AndOp>::OpConversionPattern; | ||
|
||
LogicalResult | ||
matchAndRewrite(AndOp op, OpAdaptor adaptor, | ||
ConversionPatternRewriter &rewriter) const override { | ||
SmallVector<bool> nonInverts(adaptor.getInputs().size(), false); | ||
rewriter.replaceOpWithNewOp<aig::AndInverterOp>(op, adaptor.getInputs(), | ||
nonInverts); | ||
return success(); | ||
} | ||
}; | ||
|
||
/// Lower a comb::OrOp operation to aig::AndInverterOp with invert flags | ||
struct CombOrOpConversion : OpConversionPattern<OrOp> { | ||
using OpConversionPattern<OrOp>::OpConversionPattern; | ||
|
||
LogicalResult | ||
matchAndRewrite(OrOp op, OpAdaptor adaptor, | ||
ConversionPatternRewriter &rewriter) const override { | ||
// Implement Or using And and invert flags: a | b = ~(~a & ~b) | ||
SmallVector<bool> allInverts(adaptor.getInputs().size(), true); | ||
auto andOp = rewriter.create<aig::AndInverterOp>( | ||
op.getLoc(), adaptor.getInputs(), allInverts); | ||
rewriter.replaceOpWithNewOp<aig::AndInverterOp>(op, andOp, | ||
/*invert=*/true); | ||
return success(); | ||
} | ||
}; | ||
|
||
/// Lower a comb::XorOp operation to AIG operations | ||
struct CombXorOpConversion : OpConversionPattern<XorOp> { | ||
using OpConversionPattern<XorOp>::OpConversionPattern; | ||
|
||
LogicalResult | ||
matchAndRewrite(XorOp op, OpAdaptor adaptor, | ||
ConversionPatternRewriter &rewriter) const override { | ||
if (op.getNumOperands() != 2) | ||
return failure(); | ||
// Xor using And with invert flags: a ^ b = (a | b) & (~a | ~b) | ||
|
||
// (a | b) = ~(~a & ~b) | ||
// (~a | ~b) = ~(a & b) | ||
auto inputs = adaptor.getInputs(); | ||
SmallVector<bool> allInverts(inputs.size(), true); | ||
SmallVector<bool> allNotInverts(inputs.size(), false); | ||
|
||
auto notAAndNotB = | ||
rewriter.create<aig::AndInverterOp>(op.getLoc(), inputs, allInverts); | ||
auto aAndB = | ||
rewriter.create<aig::AndInverterOp>(op.getLoc(), inputs, allNotInverts); | ||
|
||
rewriter.replaceOpWithNewOp<aig::AndInverterOp>(op, notAAndNotB, aAndB, | ||
/*lhs_invert=*/true, | ||
/*rhs_invert=*/true); | ||
return success(); | ||
} | ||
}; | ||
|
||
} // namespace | ||
|
||
//===----------------------------------------------------------------------===// | ||
// Convert Comb to AIG pass | ||
//===----------------------------------------------------------------------===// | ||
|
||
namespace { | ||
struct ConvertCombToAIGPass | ||
: public impl::ConvertCombToAIGBase<ConvertCombToAIGPass> { | ||
void runOnOperation() override; | ||
}; | ||
} // namespace | ||
|
||
static void populateCombToAIGConversionPatterns(RewritePatternSet &patterns) { | ||
patterns.add<CombAndOpConversion, CombOrOpConversion, CombXorOpConversion>( | ||
patterns.getContext()); | ||
} | ||
|
||
void ConvertCombToAIGPass::runOnOperation() { | ||
ConversionTarget target(getContext()); | ||
target.addIllegalDialect<comb::CombDialect>(); | ||
target.addLegalDialect<aig::AIGDialect>(); | ||
|
||
RewritePatternSet patterns(&getContext()); | ||
populateCombToAIGConversionPatterns(patterns); | ||
|
||
if (failed(mlir::applyPartialConversion(getOperation(), target, | ||
std::move(patterns)))) | ||
return signalPassFailure(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// RUN: circt-opt %s --convert-comb-to-aig | FileCheck %s | ||
|
||
// CHECK-LABEL: @test | ||
hw.module @test(in %arg0: i32, in %arg1: i32, in %arg2: i32, in %arg3: i32, out out0: i32, out out1: i32, out out2: i32) { | ||
// CHECK-NEXT: %[[OR_TMP:.+]] = aig.and_inv not %arg0, not %arg1, not %arg2, not %arg3 : i32 | ||
// CHECK-NEXT: %[[OR:.+]] = aig.and_inv not %0 : i32 | ||
// CHECK-NEXT: %[[AND:.+]] = aig.and_inv %arg0, %arg1, %arg2, %arg3 : i32 | ||
// CHECK-NEXT: %[[XOR_NOT_AND:.+]] = aig.and_inv not %arg0, not %arg1 : i32 | ||
// CHECK-NEXT: %[[XOR_AND:.+]] = aig.and_inv %arg0, %arg1 : i32 | ||
// CHECK-NEXT: %[[XOR:.+]] = aig.and_inv not %[[XOR_NOT_AND]], not %[[XOR_AND]] : i32 | ||
// CHECK-NEXT: hw.output %[[OR]], %[[AND]], %[[XOR]] : i32, i32, i32 | ||
%0 = comb.or %arg0, %arg1, %arg2, %arg3 : i32 | ||
%1 = comb.and %arg0, %arg1, %arg2, %arg3 : i32 | ||
%2 = comb.xor %arg0, %arg1 : i32 | ||
hw.output %0, %1, %2 : i32, i32, i32 | ||
} |