CIRCT 23.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 SynthChoiceOpConversion : OpConversionPattern<synth::ChoiceOp> {
36 using OpConversionPattern<synth::ChoiceOp>::OpConversionPattern;
37 LogicalResult
38 matchAndRewrite(synth::ChoiceOp op, OpAdaptor adaptor,
39 ConversionPatternRewriter &rewriter) const override {
40 // Use the first input as the output, and ignore the rest.
41 rewriter.replaceOp(op, adaptor.getInputs().front());
42 return success();
43 }
44};
45
46struct SynthAndInverterOpConversion
47 : OpConversionPattern<synth::aig::AndInverterOp> {
48 using OpConversionPattern<synth::aig::AndInverterOp>::OpConversionPattern;
49 LogicalResult
50 matchAndRewrite(synth::aig::AndInverterOp op, OpAdaptor adaptor,
51 ConversionPatternRewriter &rewriter) const override {
52 // Convert to comb.and + comb.xor + hw.constant
53 auto width = op.getResult().getType().getIntOrFloatBitWidth();
54 auto allOnes =
55 hw::ConstantOp::create(rewriter, op.getLoc(), APInt::getAllOnes(width));
56 SmallVector<Value> operands;
57 operands.reserve(op.getNumOperands());
58 for (auto [input, inverted] : llvm::zip(op.getOperands(), op.getInverted()))
59 operands.push_back(inverted ? rewriter.createOrFold<comb::XorOp>(
60 op.getLoc(), input, allOnes, true)
61 : input);
62 // NOTE: Use createOrFold to avoid creating a new operation if possible.
63 rewriter.replaceOp(
64 op, rewriter.createOrFold<comb::AndOp>(op.getLoc(), operands, true));
65 return success();
66 }
67};
68
69struct SynthMajorityInverterOpConversion
70 : OpConversionPattern<synth::mig::MajorityInverterOp> {
72 synth::mig::MajorityInverterOp>::OpConversionPattern;
73 LogicalResult
74 matchAndRewrite(synth::mig::MajorityInverterOp op, OpAdaptor adaptor,
75 ConversionPatternRewriter &rewriter) const override {
76 // Only handle 1 or 3-input majority inverter for now.
77 if (op.getNumOperands() > 3)
78 return failure();
79
80 auto getOperand = [&](unsigned idx) {
81 auto input = op.getInputs()[idx];
82 if (!op.getInverted()[idx])
83 return input;
84 auto width = input.getType().getIntOrFloatBitWidth();
85 auto allOnes = hw::ConstantOp::create(rewriter, op.getLoc(),
86 APInt::getAllOnes(width));
87 return rewriter.createOrFold<comb::XorOp>(op.getLoc(), input, allOnes,
88 true);
89 };
90
91 if (op.getNumOperands() == 1) {
92 rewriter.replaceOp(op, getOperand(0));
93 return success();
94 }
95
96 assert(op.getNumOperands() == 3 && "Expected 3 operands for majority op");
97 SmallVector<Value, 3> inputs;
98 for (size_t i = 0; i < 3; ++i)
99 inputs.push_back(getOperand(i));
100
101 // MAJ(x, y, z) = x & y | x & z | y & z
102 auto getProduct = [&](unsigned idx1, unsigned idx2) {
103 return rewriter.createOrFold<comb::AndOp>(
104 op.getLoc(), ValueRange{inputs[idx1], inputs[idx2]}, true);
105 };
106
107 SmallVector<Value, 3> operands;
108 operands.push_back(getProduct(0, 1));
109 operands.push_back(getProduct(0, 2));
110 operands.push_back(getProduct(1, 2));
111
112 rewriter.replaceOp(
113 op, rewriter.createOrFold<comb::OrOp>(op.getLoc(), operands, true));
114 return success();
115 }
116};
117
118} // namespace
119
120//===----------------------------------------------------------------------===//
121// Convert Synth to Comb pass
122//===----------------------------------------------------------------------===//
123
124namespace {
125struct ConvertSynthToCombPass
126 : public impl::ConvertSynthToCombBase<ConvertSynthToCombPass> {
127
128 void runOnOperation() override;
129 using ConvertSynthToCombBase<ConvertSynthToCombPass>::ConvertSynthToCombBase;
130};
131} // namespace
132
133static void populateSynthToCombConversionPatterns(RewritePatternSet &patterns) {
134 patterns.add<SynthChoiceOpConversion, SynthAndInverterOpConversion,
135 SynthMajorityInverterOpConversion>(patterns.getContext());
136}
137
138void ConvertSynthToCombPass::runOnOperation() {
139 ConversionTarget target(getContext());
140 target.addLegalDialect<comb::CombDialect, hw::HWDialect>();
141 target.addIllegalDialect<synth::SynthDialect>();
142
143 RewritePatternSet patterns(&getContext());
145
146 if (failed(mlir::applyPartialConversion(getOperation(), target,
147 std::move(patterns))))
148 return signalPassFailure();
149}
assert(baseType &&"element must be base type")
static Location getLoc(DefSlot slot)
Definition Mem2Reg.cpp:216
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