CIRCT  20.0.0git
LowerComb.cpp
Go to the documentation of this file.
1 //===- LowerComb.cpp - Lower some ops in comb -------------------*- 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 
11 #include "circt/Dialect/HW/HWOps.h"
12 #include "mlir/Transforms/DialectConversion.h"
13 #include "llvm/ADT/TypeSwitch.h"
14 
15 using namespace circt;
16 using namespace circt::comb;
17 
18 namespace circt {
19 namespace comb {
20 #define GEN_PASS_DEF_LOWERCOMB
21 #include "circt/Dialect/Comb/Passes.h.inc"
22 } // namespace comb
23 } // namespace circt
24 
25 namespace {
26 /// Lower truth tables to mux trees.
27 struct TruthTableToMuxTree : public OpConversionPattern<TruthTableOp> {
28  using OpConversionPattern::OpConversionPattern;
29 
30 private:
31  /// Get a mux tree for `inputs` corresponding to the given truth table. Do
32  /// this recursively by dividing the table in half for each input.
33  // NOLINTNEXTLINE(misc-no-recursion)
34  Value getMux(Location loc, OpBuilder &b, Value t, Value f,
35  ArrayRef<bool> table, Operation::operand_range inputs) const {
36  assert(table.size() == (1ull << inputs.size()));
37  if (table.size() == 1)
38  return table.front() ? t : f;
39 
40  size_t half = table.size() / 2;
41  Value if1 =
42  getMux(loc, b, t, f, table.drop_front(half), inputs.drop_front());
43  Value if0 =
44  getMux(loc, b, t, f, table.drop_back(half), inputs.drop_front());
45  return b.create<MuxOp>(loc, inputs.front(), if1, if0, false);
46  }
47 
48 public:
49  LogicalResult matchAndRewrite(TruthTableOp op, OpAdaptor adaptor,
50  ConversionPatternRewriter &b) const override {
51  Location loc = op.getLoc();
52  SmallVector<bool> table(
53  llvm::map_range(op.getLookupTableAttr().getAsValueRange<IntegerAttr>(),
54  [](const APInt &a) { return !a.isZero(); }));
55  Value t = b.create<hw::ConstantOp>(loc, b.getIntegerAttr(b.getI1Type(), 1));
56  Value f = b.create<hw::ConstantOp>(loc, b.getIntegerAttr(b.getI1Type(), 0));
57 
58  Value tree = getMux(loc, b, t, f, table, op.getInputs());
59  b.modifyOpInPlace(tree.getDefiningOp(), [&]() {
60  tree.getDefiningOp()->setDialectAttrs(op->getDialectAttrs());
61  });
62  b.replaceOp(op, tree);
63  return success();
64  }
65 };
66 } // namespace
67 
68 namespace {
69 class LowerCombPass : public impl::LowerCombBase<LowerCombPass> {
70 public:
71  using LowerCombBase::LowerCombBase;
72 
73  void runOnOperation() override;
74 };
75 } // namespace
76 
77 void LowerCombPass::runOnOperation() {
78  ModuleOp module = getOperation();
79 
80  ConversionTarget target(getContext());
81  RewritePatternSet patterns(&getContext());
82  target.markUnknownOpDynamicallyLegal([](Operation *) { return true; });
83  target.addIllegalOp<TruthTableOp>();
84 
85  patterns.add<TruthTableToMuxTree>(patterns.getContext());
86 
87  if (failed(applyPartialConversion(module, target, std::move(patterns))))
88  return signalPassFailure();
89 }
assert(baseType &&"element must be base type")
def create(data_type, value)
Definition: hw.py:393
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
Definition: comb.py:1