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"
38 matchAndRewrite(synth::ChoiceOp op, OpAdaptor adaptor,
39 ConversionPatternRewriter &rewriter)
const override {
41 rewriter.replaceOp(op, adaptor.getInputs().front());
46struct SynthAndInverterOpConversion
50 matchAndRewrite(synth::aig::AndInverterOp op, OpAdaptor adaptor,
51 ConversionPatternRewriter &rewriter)
const override {
53 auto width = op.getResult().getType().getIntOrFloatBitWidth();
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)
64 op, rewriter.createOrFold<
comb::AndOp>(op.getLoc(), operands,
true));
69struct SynthMajorityInverterOpConversion
74 matchAndRewrite(synth::mig::MajorityInverterOp op, OpAdaptor adaptor,
75 ConversionPatternRewriter &rewriter)
const override {
76 auto getOperand = [&](
unsigned idx) {
77 auto input = adaptor.getInputs()[idx];
78 if (!op.getInverted()[idx])
80 auto width = input.getType().getIntOrFloatBitWidth();
82 APInt::getAllOnes(width));
83 return rewriter.createOrFold<
comb::XorOp>(op.getLoc(), input, allOnes,
87 if (op.getNumOperands() == 1) {
88 rewriter.replaceOp(op, getOperand(0));
92 SmallVector<Value> inputs;
93 inputs.reserve(op.getNumOperands());
94 for (
size_t i = 0, e = op.getNumOperands(); i < e; ++i)
95 inputs.push_back(getOperand(i));
99 auto getProduct = [&](ArrayRef<unsigned> indices) {
100 SmallVector<Value> productOperands;
101 productOperands.reserve(indices.size());
102 for (
auto idx : indices)
103 productOperands.push_back(inputs[idx]);
104 return rewriter.createOrFold<
comb::AndOp>(op.getLoc(), productOperands,
108 SmallVector<Value> operands;
109 SmallVector<unsigned> subset;
110 const unsigned threshold = op.getNumOperands() / 2 + 1;
112 auto enumerateProducts = [&](
auto &&self,
unsigned start) ->
void {
113 if (subset.size() == threshold) {
114 operands.push_back(getProduct(subset));
118 const unsigned remaining = threshold - subset.size();
119 assert(start + remaining <= op.getNumOperands() &&
120 "Not enough operands left to reach threshold");
121 for (
unsigned i = start, e = op.getNumOperands() - remaining; i <= e;
128 enumerateProducts(enumerateProducts, 0);
131 op, rewriter.createOrFold<
comb::OrOp>(op.getLoc(), operands,
true));
143struct ConvertSynthToCombPass
144 :
public impl::ConvertSynthToCombBase<ConvertSynthToCombPass> {
146 void runOnOperation()
override;
147 using ConvertSynthToCombBase<ConvertSynthToCombPass>::ConvertSynthToCombBase;
152 patterns.add<SynthChoiceOpConversion, SynthAndInverterOpConversion,
153 SynthMajorityInverterOpConversion>(
patterns.getContext());
156void ConvertSynthToCombPass::runOnOperation() {
157 ConversionTarget target(getContext());
158 target.addLegalDialect<comb::CombDialect, hw::HWDialect>();
159 target.addIllegalDialect<synth::SynthDialect>();
161 RewritePatternSet
patterns(&getContext());
164 if (failed(mlir::applyPartialConversion(getOperation(), target,
166 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.