CIRCT 20.0.0git
Loading...
Searching...
No Matches
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
18#include "circt/Support/Debug.h"
19#include "mlir/IR/ImplicitLocOpBuilder.h"
20#include "mlir/Pass/Pass.h"
21#include "llvm/Support/Debug.h"
22
23#define DEBUG_TYPE "firrtl-passive-wires"
24
25namespace circt {
26namespace firrtl {
27#define GEN_PASS_DEF_PASSIVEWIRES
28#include "circt/Dialect/FIRRTL/Passes.h.inc"
29} // namespace firrtl
30} // namespace circt
31
32using namespace circt;
33using namespace firrtl;
34
35static bool hasFlip(Type t) {
36 if (auto type = type_dyn_cast<FIRRTLBaseType>(t))
37 return !type.isPassive();
38 return false;
39}
40
41//===----------------------------------------------------------------------===//
42// Pass Infrastructure
43//===----------------------------------------------------------------------===//
44
45namespace {
46struct PassiveWiresPass
47 : public circt::firrtl::impl::PassiveWiresBase<PassiveWiresPass> {
48 void runOnOperation() override;
49};
50} // end anonymous namespace
51
52// This is the main entrypoint for the lowering pass.
53void PassiveWiresPass::runOnOperation() {
54 LLVM_DEBUG(debugPassHeader(this) << "\n";);
55 auto module = getOperation();
56
57 // First, expand any connects to resolve flips.
58 SmallVector<Operation *> worklist;
59 module.walk([&](Operation *op) -> WalkResult {
60 if (auto wire = dyn_cast<WireOp>(op)) {
61 if (hasFlip(wire.getType(0)))
62 worklist.push_back(wire);
63 return WalkResult::advance();
64 }
65 if (!isa<ConnectOp, MatchingConnectOp>(op))
66 return WalkResult::advance();
67 // connect/matchingconnect
68 if (!hasFlip(op->getOperand(0).getType()))
69 return WalkResult::advance();
70
71 mlir::ImplicitLocOpBuilder builder(op->getLoc(), op);
72 // This will "blow out" a connect to passive pieces
73 emitConnect(builder, op->getOperand(0), op->getOperand(1));
74 op->erase();
75 return WalkResult::advance();
76 });
77
78 // Second, remove flips from most things.
79 while (!worklist.empty()) {
80 auto *op = worklist.back();
81 worklist.pop_back();
82 auto r = op->getResult(0);
83 if (!hasFlip(r.getType()))
84 continue;
85 for (auto users : r.getUsers())
86 worklist.push_back(users);
87 // In-place updates is safe as consumers don't care about flip.
88 r.setType(type_cast<FIRRTLBaseType>(r.getType()).getPassiveType());
89 }
90}
91
92/// This is the pass constructor.
93std::unique_ptr<mlir::Pass> circt::firrtl::createPassiveWiresPass() {
94 return std::make_unique<PassiveWiresPass>();
95}
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.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
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