CIRCT  20.0.0git
LowerConcatRef.cpp
Go to the documentation of this file.
1 //===- LowerConcatRef.cpp - moore.concat_ref lowering ---------------------===//
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 file defines the LowerConcatRef pass.
10 // It's used to disassemble the moore.concat_ref. Which is tricky to lower
11 // directly. For example, disassemble "{a, b} = c" onto "a = c[7:3]"
12 // and "b = c[2:0]".
13 //
14 //===----------------------------------------------------------------------===//
15 
18 #include "mlir/Transforms/DialectConversion.h"
19 
20 namespace circt {
21 namespace moore {
22 #define GEN_PASS_DEF_LOWERCONCATREF
23 #include "circt/Dialect/Moore/MoorePasses.h.inc"
24 } // namespace moore
25 } // namespace circt
26 
27 using namespace circt;
28 using namespace moore;
29 using namespace mlir;
30 
31 namespace {
32 
33 // A helper function for collecting the non-concatRef operands of concatRef.
34 static void collectOperands(Value operand, SmallVectorImpl<Value> &operands) {
35  if (auto concatRefOp = operand.getDefiningOp<ConcatRefOp>())
36  for (auto nestedOperand : concatRefOp.getValues())
37  collectOperands(nestedOperand, operands);
38  else
39  operands.push_back(operand);
40 }
41 
42 template <typename OpTy>
43 struct ConcatRefLowering : public OpConversionPattern<OpTy> {
45  using OpAdaptor = typename OpTy::Adaptor;
46 
47  LogicalResult
48  matchAndRewrite(OpTy op, OpAdaptor adaptor,
49  ConversionPatternRewriter &rewriter) const override {
50  // Use to collect the operands of concatRef.
51  SmallVector<Value, 4> operands;
52  collectOperands(op.getDst(), operands);
53  auto srcWidth =
54  cast<UnpackedType>(op.getSrc().getType()).getBitSize().value();
55 
56  // Disassemble assignments with the LHS is concatRef. And create new
57  // corresponding assignments using non-concatRef LHS.
58  for (auto operand : operands) {
59  auto type = cast<RefType>(operand.getType()).getNestedType();
60  auto width = type.getBitSize().value();
61 
62  rewriter.setInsertionPoint(op);
63  // FIXME: Need to estimate whether the bits range is from large to
64  // small or vice versa. Like "logic [7:0] or [0:7]".
65 
66  // Only able to correctly handle the situation like "[7:0]" now.
67  auto extract = rewriter.create<ExtractOp>(op.getLoc(), type, op.getSrc(),
68  srcWidth - width);
69 
70  // Update the real bit width of RHS of assignment. Like "c" the above
71  // description mentioned.
72  srcWidth = srcWidth - width;
73 
74  rewriter.create<OpTy>(op.getLoc(), operand, extract);
75  }
76  rewriter.eraseOp(op);
77  return success();
78  }
79 };
80 
81 struct LowerConcatRefPass
82  : public circt::moore::impl::LowerConcatRefBase<LowerConcatRefPass> {
83  void runOnOperation() override;
84 };
85 
86 } // namespace
87 
88 std::unique_ptr<mlir::Pass> circt::moore::createLowerConcatRefPass() {
89  return std::make_unique<LowerConcatRefPass>();
90 }
91 
92 void LowerConcatRefPass::runOnOperation() {
93  MLIRContext &context = getContext();
94  ConversionTarget target(context);
95 
96  target.addDynamicallyLegalOp<ContinuousAssignOp, BlockingAssignOp,
97  NonBlockingAssignOp>([](auto op) {
98  return !op->getOperand(0).template getDefiningOp<ConcatRefOp>();
99  });
100 
101  target.addLegalDialect<MooreDialect>();
102  RewritePatternSet patterns(&context);
103  patterns.add<ConcatRefLowering<ContinuousAssignOp>,
104  ConcatRefLowering<BlockingAssignOp>,
105  ConcatRefLowering<NonBlockingAssignOp>>(&context);
106 
107  if (failed(
108  applyPartialConversion(getOperation(), target, std::move(patterns))))
109  signalPassFailure();
110 }
int32_t width
Definition: FIRRTL.cpp:40
std::unique_ptr< mlir::Pass > createLowerConcatRefPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21