CIRCT 22.0.0git
Loading...
Searching...
No Matches
SynthToComb.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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 is the main Synth to Comb Conversion Pass Implementation.
10//
11//===----------------------------------------------------------------------===//
12
18#include "mlir/Pass/Pass.h"
19#include "mlir/Transforms/DialectConversion.h"
20
21namespace circt {
22#define GEN_PASS_DEF_CONVERTSYNTHTOCOMB
23#include "circt/Conversion/Passes.h.inc"
24} // namespace circt
25
26using namespace circt;
27using namespace comb;
28
29//===----------------------------------------------------------------------===//
30// Conversion patterns
31//===----------------------------------------------------------------------===//
32
33namespace {
34
35struct SynthAndInverterOpConversion
36 : OpConversionPattern<synth::aig::AndInverterOp> {
37 using OpConversionPattern<synth::aig::AndInverterOp>::OpConversionPattern;
38 LogicalResult
39 matchAndRewrite(synth::aig::AndInverterOp op, OpAdaptor adaptor,
40 ConversionPatternRewriter &rewriter) const override {
41 // Convert to comb.and + comb.xor + hw.constant
42 auto width = op.getResult().getType().getIntOrFloatBitWidth();
43 auto allOnes =
44 hw::ConstantOp::create(rewriter, op.getLoc(), APInt::getAllOnes(width));
45 SmallVector<Value> operands;
46 operands.reserve(op.getNumOperands());
47 for (auto [input, inverted] : llvm::zip(op.getOperands(), op.getInverted()))
48 operands.push_back(inverted ? rewriter.createOrFold<comb::XorOp>(
49 op.getLoc(), input, allOnes, true)
50 : input);
51 // NOTE: Use createOrFold to avoid creating a new operation if possible.
52 rewriter.replaceOp(
53 op, rewriter.createOrFold<comb::AndOp>(op.getLoc(), operands, true));
54 return success();
55 }
56};
57
58struct SynthMajorityInverterOpConversion
59 : OpConversionPattern<synth::mig::MajorityInverterOp> {
61 synth::mig::MajorityInverterOp>::OpConversionPattern;
62 LogicalResult
63 matchAndRewrite(synth::mig::MajorityInverterOp op, OpAdaptor adaptor,
64 ConversionPatternRewriter &rewriter) const override {
65 // Only handle 1 or 3-input majority inverter for now.
66 if (op.getNumOperands() > 3)
67 return failure();
68
69 auto getOperand = [&](unsigned idx) {
70 auto input = op.getInputs()[idx];
71 if (!op.getInverted()[idx])
72 return input;
73 auto width = input.getType().getIntOrFloatBitWidth();
74 auto allOnes = hw::ConstantOp::create(rewriter, op.getLoc(),
75 APInt::getAllOnes(width));
76 return rewriter.createOrFold<comb::XorOp>(op.getLoc(), input, allOnes,
77 true);
78 };
79
80 if (op.getNumOperands() == 1) {
81 rewriter.replaceOp(op, getOperand(0));
82 return success();
83 }
84
85 assert(op.getNumOperands() == 3 && "Expected 3 operands for majority op");
86 SmallVector<Value, 3> inputs;
87 for (size_t i = 0; i < 3; ++i)
88 inputs.push_back(getOperand(i));
89
90 // MAJ(x, y, z) = x & y | x & z | y & z
91 auto getProduct = [&](unsigned idx1, unsigned idx2) {
92 return rewriter.createOrFold<comb::AndOp>(
93 op.getLoc(), ValueRange{inputs[idx1], inputs[idx2]}, true);
94 };
95
96 SmallVector<Value, 3> operands;
97 operands.push_back(getProduct(0, 1));
98 operands.push_back(getProduct(0, 2));
99 operands.push_back(getProduct(1, 2));
100
101 rewriter.replaceOp(
102 op, rewriter.createOrFold<comb::OrOp>(op.getLoc(), operands, true));
103 return success();
104 }
105};
106
107} // namespace
108
109//===----------------------------------------------------------------------===//
110// Convert Synth to Comb pass
111//===----------------------------------------------------------------------===//
112
113namespace {
114struct ConvertSynthToCombPass
115 : public impl::ConvertSynthToCombBase<ConvertSynthToCombPass> {
116
117 void runOnOperation() override;
118 using ConvertSynthToCombBase<ConvertSynthToCombPass>::ConvertSynthToCombBase;
119};
120} // namespace
121
122static void populateSynthToCombConversionPatterns(RewritePatternSet &patterns) {
123 patterns.add<SynthAndInverterOpConversion, SynthMajorityInverterOpConversion>(
124 patterns.getContext());
125}
126
127void ConvertSynthToCombPass::runOnOperation() {
128 ConversionTarget target(getContext());
129 target.addLegalDialect<comb::CombDialect, hw::HWDialect>();
130 target.addIllegalDialect<synth::SynthDialect>();
131
132 RewritePatternSet patterns(&getContext());
134
135 if (failed(mlir::applyPartialConversion(getOperation(), target,
136 std::move(patterns))))
137 return signalPassFailure();
138}
assert(baseType &&"element must be base type")
static void populateSynthToCombConversionPatterns(RewritePatternSet &patterns)
create(data_type, value)
Definition hw.py:433
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition comb.py:1