18#include "mlir/Pass/Pass.h"
19#include "mlir/Transforms/DialectConversion.h"
22#define GEN_PASS_DEF_CONVERTSYNTHTOCOMB
23#include "circt/Conversion/Passes.h.inc"
36static Value materializeInvertedInput(Location loc, Value input,
bool inverted,
37 ConversionPatternRewriter &rewriter,
41 auto width = input.getType().getIntOrFloatBitWidth();
44 return rewriter.createOrFold<
comb::XorOp>(loc, input, allOnes,
true);
50 matchAndRewrite(synth::ChoiceOp op, OpAdaptor adaptor,
51 ConversionPatternRewriter &rewriter)
const override {
53 rewriter.replaceOp(op, adaptor.getInputs().front());
58template <
typename SynthOp>
63 virtual Value createOp(Location loc, ArrayRef<Value> inputs,
64 ConversionPatternRewriter &rewriter)
const = 0;
67 matchAndRewrite(SynthOp op,
typename SynthOp::Adaptor adaptor,
68 ConversionPatternRewriter &rewriter)
const override {
69 SmallVector<Value> operands;
70 operands.reserve(op.getNumOperands());
72 for (
auto [input, inverted] :
73 llvm::zip(adaptor.getOperands(), op.getInverted()))
74 operands.push_back(materializeInvertedInput(op.
getLoc(), input, inverted,
77 rewriter.replaceOp(op, createOp(op.getLoc(), operands, rewriter));
82struct SynthAndInverterOpConversion
83 : SynthInverterOpConversion<synth::aig::AndInverterOp> {
84 using SynthInverterOpConversion<
85 synth::aig::AndInverterOp>::SynthInverterOpConversion;
86 Value createOp(Location loc, ArrayRef<Value> inputs,
87 ConversionPatternRewriter &rewriter)
const override {
88 return rewriter.createOrFold<
comb::AndOp>(loc, inputs,
true);
92struct SynthXorInverterOpConversion
93 : SynthInverterOpConversion<synth::XorInverterOp> {
94 using SynthInverterOpConversion<
95 synth::XorInverterOp>::SynthInverterOpConversion;
96 Value createOp(Location loc, ArrayRef<Value> inputs,
97 ConversionPatternRewriter &rewriter)
const override {
98 return rewriter.createOrFold<
comb::XorOp>(loc, inputs,
true);
102struct SynthDotOpConversion : SynthInverterOpConversion<synth::DotOp> {
103 using SynthInverterOpConversion<synth::DotOp>::SynthInverterOpConversion;
104 Value createOp(Location loc, ArrayRef<Value> inputs,
105 ConversionPatternRewriter &rewriter)
const override {
106 assert(inputs.size() == 3 &&
"expected exactly three inputs");
108 rewriter.createOrFold<
comb::AndOp>(loc, inputs[0], inputs[1],
true);
109 auto zOrXy = rewriter.createOrFold<
comb::OrOp>(loc, inputs[2], xy,
true);
110 return rewriter.createOrFold<
comb::XorOp>(loc, inputs[0], zOrXy,
true);
114struct SynthMajorityOpConversion
115 : SynthInverterOpConversion<synth::MajorityOp> {
116 using SynthInverterOpConversion<synth::MajorityOp>::SynthInverterOpConversion;
117 Value createOp(Location loc, ArrayRef<Value> inputs,
118 ConversionPatternRewriter &rewriter)
const override {
119 assert(inputs.size() == 3 &&
"expected exactly three inputs");
121 rewriter.createOrFold<
comb::AndOp>(loc, inputs[0], inputs[1],
true);
123 rewriter.createOrFold<
comb::AndOp>(loc, inputs[0], inputs[2],
true);
125 rewriter.createOrFold<
comb::AndOp>(loc, inputs[1], inputs[2],
true);
126 auto abOrAc = rewriter.createOrFold<
comb::OrOp>(loc, ab, ac,
true);
127 return rewriter.createOrFold<
comb::OrOp>(loc, abOrAc, bc,
true);
131struct SynthOneHotOpConversion : SynthInverterOpConversion<synth::OneHotOp> {
132 using SynthInverterOpConversion<synth::OneHotOp>::SynthInverterOpConversion;
133 Value createOp(Location loc, ArrayRef<Value> inputs,
134 ConversionPatternRewriter &rewriter)
const override {
135 assert(inputs.size() == 3 &&
"expected exactly three inputs");
136 auto width = inputs[0].getType().getIntOrFloatBitWidth();
141 auto notA = rewriter.createOrFold<
comb::XorOp>(loc, inputs[0],
142 allOnes.getResult(),
true);
143 auto notB = rewriter.createOrFold<
comb::XorOp>(loc, inputs[1],
144 allOnes.getResult(),
true);
145 auto notC = rewriter.createOrFold<
comb::XorOp>(loc, inputs[2],
146 allOnes.getResult(),
true);
149 loc, ValueRange{inputs[0], notB, notC},
true);
151 loc, ValueRange{notA, inputs[1], notC},
true);
153 loc, ValueRange{notA, notB, inputs[2]},
true);
155 loc, ValueRange{aOnly, bOnly, cOnly},
true);
159struct SynthMuxInverterOpConversion
160 : SynthInverterOpConversion<synth::MuxInverterOp> {
161 using SynthInverterOpConversion<
162 synth::MuxInverterOp>::SynthInverterOpConversion;
164 Value createOp(Location loc, ArrayRef<Value> inputs,
165 ConversionPatternRewriter &rewriter)
const override {
166 assert(inputs.size() == 3 &&
"expected exactly three inputs");
168 auto width = inputs[0].getType().getIntOrFloatBitWidth();
173 rewriter.createOrFold<
comb::XorOp>(loc, inputs[0], allOnes,
true);
175 rewriter.createOrFold<
comb::AndOp>(loc, inputs[0], inputs[1],
true);
177 rewriter.createOrFold<
comb::AndOp>(loc, notCond, inputs[2],
true);
179 return rewriter.createOrFold<
comb::OrOp>(loc, trueValue, falseValue,
true);
190struct ConvertSynthToCombPass
191 :
public impl::ConvertSynthToCombBase<ConvertSynthToCombPass> {
193 void runOnOperation()
override;
194 using ConvertSynthToCombBase<ConvertSynthToCombPass>::ConvertSynthToCombBase;
199 patterns.add<SynthChoiceOpConversion, SynthAndInverterOpConversion,
200 SynthXorInverterOpConversion, SynthMuxInverterOpConversion,
201 SynthDotOpConversion, SynthMajorityOpConversion,
202 SynthOneHotOpConversion>(
patterns.getContext());
205void ConvertSynthToCombPass::runOnOperation() {
206 ConversionTarget target(getContext());
207 target.addLegalDialect<comb::CombDialect, hw::HWDialect>();
208 target.addIllegalDialect<synth::SynthDialect>();
210 RewritePatternSet
patterns(&getContext());
213 if (failed(mlir::applyPartialConversion(getOperation(), target,
215 return signalPassFailure();
assert(baseType &&"element must be base type")
static Location getLoc(DefSlot slot)
static void populateSynthToCombConversionPatterns(RewritePatternSet &patterns)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.