CIRCT 20.0.0git
Loading...
Searching...
No Matches
AddTaps.cpp
Go to the documentation of this file.
1//===- AddTaps.cpp --------------------------------------------------------===//
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
13#include "mlir/Pass/Pass.h"
14
15namespace circt {
16namespace arc {
17#define GEN_PASS_DEF_ADDTAPS
18#include "circt/Dialect/Arc/ArcPasses.h.inc"
19} // namespace arc
20} // namespace circt
21
22using namespace circt;
23using namespace arc;
24using namespace hw;
25
26namespace {
27struct AddTapsPass : public arc::impl::AddTapsBase<AddTapsPass> {
28 using AddTapsBase::AddTapsBase;
29
30 void runOnOperation() override {
31 getOperation().walk([&](Operation *op) {
32 TypeSwitch<Operation *>(op)
33 .Case<HWModuleOp, sv::WireOp, hw::WireOp>([&](auto op) { tap(op); })
34 .Default([&](auto) { tapIfNamed(op); });
35 });
36 }
37
38 // Add taps for all module ports.
39 void tap(HWModuleOp moduleOp) {
40 if (!tapPorts)
41 return;
42 auto *outputOp = moduleOp.getBodyBlock()->getTerminator();
43 ModulePortInfo ports(moduleOp.getPortList());
44
45 // Add taps to inputs.
46 auto builder = OpBuilder::atBlockBegin(moduleOp.getBodyBlock());
47 for (auto [port, arg] :
48 llvm::zip(ports.getInputs(), moduleOp.getBodyBlock()->getArguments()))
49 buildTap(builder, arg.getLoc(), arg, port.getName());
50
51 // Add taps to outputs.
52 builder.setInsertionPoint(outputOp);
53 for (auto [port, result] :
54 llvm::zip(ports.getOutputs(), outputOp->getOperands()))
55 buildTap(builder, result.getLoc(), result, port.getName());
56 }
57
58 // Add taps for SV wires.
59 void tap(sv::WireOp wireOp) {
60 if (!tapWires)
61 return;
62 sv::ReadInOutOp readOp;
63 for (auto *user : wireOp->getUsers())
64 if (auto op = dyn_cast<sv::ReadInOutOp>(user))
65 readOp = op;
66
67 OpBuilder builder(wireOp);
68 if (!readOp)
69 readOp = builder.create<sv::ReadInOutOp>(wireOp.getLoc(), wireOp);
70 buildTap(builder, readOp.getLoc(), readOp, wireOp.getName());
71 }
72
73 // Add taps for HW wires.
74 void tap(hw::WireOp wireOp) {
75 if (auto name = wireOp.getName(); name && tapWires) {
76 OpBuilder builder(wireOp);
77 buildTap(builder, wireOp.getLoc(), wireOp, *name);
78 }
79 wireOp.getResult().replaceAllUsesWith(wireOp.getInput());
80 wireOp->erase();
81 }
82
83 // Add taps for named values.
84 void tapIfNamed(Operation *op) {
85 if (!tapNamedValues || op->getNumResults() != 1)
86 return;
87 if (auto name = op->getAttrOfType<StringAttr>("sv.namehint")) {
88 OpBuilder builder(op);
89 buildTap(builder, op->getLoc(), op->getResult(0), name);
90 }
91 }
92
93 void buildTap(OpBuilder &builder, Location loc, Value value, StringRef name) {
94 if (name.empty())
95 return;
96 if (isa<seq::ClockType>(value.getType()))
97 value = builder.createOrFold<seq::FromClockOp>(loc, value);
98 builder.create<arc::TapOp>(loc, value, name);
99 }
100};
101} // namespace
102
103std::unique_ptr<Pass> arc::createAddTapsPass(const AddTapsOptions &options) {
104 return std::make_unique<AddTapsPass>(options);
105}
static Block * getBodyBlock(FModuleLike mod)
create(value)
Definition sv.py:106
std::unique_ptr< mlir::Pass > createAddTapsPass(const AddTapsOptions &options={})
Definition AddTaps.cpp:103
StringAttr getName(ArrayAttr names, size_t idx)
Return the name at the specified index of the ArrayAttr or null if it cannot be determined.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition hw.py:1
Definition sv.py:1
This holds a decoded list of input/inout and output ports for a module or instance.