Skip to content

Commit 4f0edf4

Browse files
committed
[AIG] Add LowerWordToBits pass
This commit ads LowerWordToBits pass that perform bit-blasting for AndInverterOp.
1 parent f2fc8c7 commit 4f0edf4

File tree

5 files changed

+126
-1
lines changed

5 files changed

+126
-1
lines changed

include/circt/Dialect/AIG/AIGPasses.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,9 @@ def LowerVariadic : Pass<"aig-lower-variadic", "hw::HWModuleOp"> {
1515
let summary = "Lower variadic AndInverter operations to binary AndInverter";
1616
}
1717

18+
def LowerWordToBits : Pass<"aig-lower-word-to-bits", "hw::HWModuleOp"> {
19+
let summary = "Lower multi-bit AndInverter to single-bit ones";
20+
let dependentDialects = ["comb::CombDialect"];
21+
}
22+
1823
#endif // CIRCT_DIALECT_AIG_AIGPASSES_TD

lib/Dialect/AIG/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ add_circt_dialect_library(CIRCTAIG
1313
MLIRAIGIncGen
1414
)
1515

16-
add_subdirectory(Transforms)
16+
add_subdirectory(Transforms)

lib/Dialect/AIG/Transforms/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
add_circt_dialect_library(CIRCTAIGTransforms
22
LowerVariadic.cpp
3+
LowerWordToBits.cpp
34

45
DEPENDS
56
CIRCTAIGPassesIncGen
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//===- LowerWordToBits.cpp - Bit-Blasting Words to Bits ---------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This pass lowers multi-bit AIG operations to single-bit ones.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "circt/Dialect/AIG/AIGOps.h"
14+
#include "circt/Dialect/AIG/AIGPasses.h"
15+
#include "circt/Dialect/Comb/CombOps.h"
16+
#include "circt/Dialect/HW/HWOps.h"
17+
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
18+
19+
#define DEBUG_TYPE "aig-lower-word-to-bits"
20+
21+
namespace circt {
22+
namespace aig {
23+
#define GEN_PASS_DEF_LOWERWORDTOBITS
24+
#include "circt/Dialect/AIG/AIGPasses.h.inc"
25+
} // namespace aig
26+
} // namespace circt
27+
28+
using namespace circt;
29+
using namespace aig;
30+
31+
//===----------------------------------------------------------------------===//
32+
// Rewrite patterns
33+
//===----------------------------------------------------------------------===//
34+
35+
namespace {
36+
37+
struct WordRewritePattern : public OpRewritePattern<AndInverterOp> {
38+
using OpRewritePattern<AndInverterOp>::OpRewritePattern;
39+
40+
LogicalResult matchAndRewrite(AndInverterOp op,
41+
PatternRewriter &rewriter) const override {
42+
auto width = op.getType().getIntOrFloatBitWidth();
43+
if (width <= 1)
44+
return failure();
45+
46+
SmallVector<Value> results;
47+
// We iterate over the width in reverse order to match the endianness of
48+
// `comb.concat`.
49+
for (int64_t i = width - 1; i >= 0; --i) {
50+
SmallVector<Value> operands;
51+
for (auto operand : op.getOperands()) {
52+
// Reuse bits if we can extract from `comb.concat` operands.
53+
if (auto concat = operand.getDefiningOp<comb::ConcatOp>()) {
54+
// For the simplicity, we only handle the case where all the
55+
// `comb.concat` operands are single-bit.
56+
if (concat.getNumOperands() == width &&
57+
llvm::all_of(concat.getOperandTypes(), [](Type type) {
58+
return type.getIntOrFloatBitWidth() == 1;
59+
})) {
60+
// Be careful with the endianness here.
61+
operands.push_back(concat.getOperand(width - i - 1));
62+
continue;
63+
}
64+
}
65+
// Otherwise, we need to extract the bit.
66+
operands.push_back(
67+
rewriter.create<comb::ExtractOp>(op.getLoc(), operand, i, 1));
68+
}
69+
results.push_back(rewriter.create<AndInverterOp>(op.getLoc(), operands,
70+
op.getInvertedAttr()));
71+
}
72+
73+
rewriter.replaceOpWithNewOp<comb::ConcatOp>(op, results);
74+
return success();
75+
}
76+
};
77+
78+
} // namespace
79+
80+
//===----------------------------------------------------------------------===//
81+
// Lower Word to Bits pass
82+
//===----------------------------------------------------------------------===//
83+
84+
namespace {
85+
struct LowerWordToBitsPass
86+
: public impl::LowerWordToBitsBase<LowerWordToBitsPass> {
87+
void runOnOperation() override;
88+
};
89+
} // namespace
90+
91+
void LowerWordToBitsPass::runOnOperation() {
92+
RewritePatternSet patterns(&getContext());
93+
patterns.add<WordRewritePattern>(&getContext());
94+
95+
mlir::FrozenRewritePatternSet frozenPatterns(std::move(patterns));
96+
mlir::GreedyRewriteConfig config;
97+
// Use top-down traversal to reuse bits from `comb.concat`.
98+
config.useTopDownTraversal = true;
99+
100+
if (failed(mlir::applyPatternsAndFoldGreedily(getOperation(), frozenPatterns,
101+
config)))
102+
return signalPassFailure();
103+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: circt-opt %s --aig-lower-word-to-bits | FileCheck %s
2+
// CHECK: hw.module @Basic
3+
hw.module @Basic(in %a: i2, in %b: i2, out f: i2) {
4+
%0 = aig.and_inv not %a, %b : i2
5+
%1 = aig.and_inv not %0, not %0 : i2
6+
// CHECK-NEXT: %[[EXTRACT_A_1:.+]] = comb.extract %a from 1
7+
// CHECK-NEXT: %[[EXTRACT_B_1:.+]] = comb.extract %b from 1
8+
// CHECK-NEXT: %[[AND_INV_0:.+]] = aig.and_inv not %[[EXTRACT_A_1]], %[[EXTRACT_B_1]]
9+
// CHECK-NEXT: %[[EXTRACT_A_0:.+]] = comb.extract %a from 0
10+
// CHECK-NEXT: %[[EXTRACT_B_0:.+]] = comb.extract %b from 0
11+
// CHECK-NEXT: %[[AND_INV_1:.+]] = aig.and_inv not %[[EXTRACT_A_0]], %[[EXTRACT_B_0]]
12+
// CHECK-NEXT: %[[AND_INV_2:.+]] = aig.and_inv not %[[AND_INV_0]], not %[[AND_INV_0]]
13+
// CHECK-NEXT: %[[AND_INV_3:.+]] = aig.and_inv not %[[AND_INV_1]], not %[[AND_INV_1]]
14+
// CHECK-NEXT: %[[CONCAT:.+]] = comb.concat %[[AND_INV_2]], %[[AND_INV_3]]
15+
hw.output %1 : i2
16+
}

0 commit comments

Comments
 (0)