CIRCT  20.0.0git
PassiveWires.cpp
Go to the documentation of this file.
1 //===- PassiveWires.cpp - Make Wires Passive --------------------*- 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 //
9 // This file defines the PassiveWires pass. This pass eliminated flips from
10 // wires with aggregate types. Since flips only determine connect direction,
11 // they are unnecessary on wires and just get in the way.
12 //
13 //===----------------------------------------------------------------------===//
14 
17 #include "mlir/Pass/Pass.h"
18 
20 #include "circt/Support/Debug.h"
21 #include "mlir/IR/ImplicitLocOpBuilder.h"
22 #include "llvm/Support/Debug.h"
23 
24 #define DEBUG_TYPE "firrtl-passive-wires"
25 
26 namespace circt {
27 namespace firrtl {
28 #define GEN_PASS_DEF_PASSIVEWIRES
29 #include "circt/Dialect/FIRRTL/Passes.h.inc"
30 } // namespace firrtl
31 } // namespace circt
32 
33 using namespace circt;
34 using namespace firrtl;
35 
36 static bool hasFlip(Type t) {
37  if (auto type = type_dyn_cast<FIRRTLBaseType>(t))
38  return !type.isPassive();
39  return false;
40 }
41 
42 //===----------------------------------------------------------------------===//
43 // Pass Infrastructure
44 //===----------------------------------------------------------------------===//
45 
46 namespace {
47 struct PassiveWiresPass
48  : public circt::firrtl::impl::PassiveWiresBase<PassiveWiresPass> {
49  void runOnOperation() override;
50 };
51 } // end anonymous namespace
52 
53 // This is the main entrypoint for the lowering pass.
54 void PassiveWiresPass::runOnOperation() {
55  LLVM_DEBUG(debugPassHeader(this) << "\n";);
56  auto module = getOperation();
57 
58  // First, expand any connects to resolve flips.
59  SmallVector<Operation *> worklist;
60  module.walk([&](Operation *op) -> WalkResult {
61  if (auto wire = dyn_cast<WireOp>(op)) {
62  if (hasFlip(wire.getType(0)))
63  worklist.push_back(wire);
64  return WalkResult::advance();
65  }
66  if (!isa<ConnectOp, MatchingConnectOp>(op))
67  return WalkResult::advance();
68  // connect/matchingconnect
69  if (!hasFlip(op->getOperand(0).getType()))
70  return WalkResult::advance();
71 
72  mlir::ImplicitLocOpBuilder builder(op->getLoc(), op);
73  // This will "blow out" a connect to passive pieces
74  emitConnect(builder, op->getOperand(0), op->getOperand(1));
75  op->erase();
76  return WalkResult::advance();
77  });
78 
79  // Second, remove flips from most things.
80  while (!worklist.empty()) {
81  auto *op = worklist.back();
82  worklist.pop_back();
83  auto r = op->getResult(0);
84  if (!hasFlip(r.getType()))
85  continue;
86  for (auto users : r.getUsers())
87  worklist.push_back(users);
88  // In-place updates is safe as consumers don't care about flip.
89  r.setType(type_cast<FIRRTLBaseType>(r.getType()).getPassiveType());
90  }
91 }
92 
93 /// This is the pass constructor.
94 std::unique_ptr<mlir::Pass> circt::firrtl::createPassiveWiresPass() {
95  return std::make_unique<PassiveWiresPass>();
96 }
static bool hasFlip(Type t)
std::unique_ptr< mlir::Pass > createPassiveWiresPass()
This is the pass constructor.
void emitConnect(OpBuilder &builder, Location loc, Value lhs, Value rhs)
Emit a connect between two values.
Definition: FIRRTLUtils.cpp:25
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
llvm::raw_ostream & debugPassHeader(const mlir::Pass *pass, int width=80)
Write a boilerplate header for a pass to the debug stream.
Definition: Debug.cpp:31