15 #include "mlir/IR/Builders.h"
16 #include "llvm/ADT/PostOrderIterator.h"
18 using namespace circt;
21 using namespace igraph;
25 #define GEN_PASS_DEF_HWELIMINATEINOUTPORTS
26 #include "circt/Dialect/SV/SVPasses.h.inc"
28 struct HWEliminateInOutPortsPass
29 :
public impl::HWEliminateInOutPortsBase<HWEliminateInOutPortsPass> {
30 using HWEliminateInOutPortsBase<
31 HWEliminateInOutPortsPass>::HWEliminateInOutPortsBase;
32 void runOnOperation()
override;
41 llvm::StringRef readSuffix,
42 llvm::StringRef writeSuffix);
44 void mapInputSignals(OpBuilder &b, Operation *inst, Value instValue,
45 SmallVectorImpl<Value> &newOperands,
46 ArrayRef<Backedge> newResults)
override;
47 void mapOutputSignals(OpBuilder &b, Operation *inst, Value instValue,
48 SmallVectorImpl<Value> &newOperands,
49 ArrayRef<Backedge> newResults)
override;
51 LogicalResult init()
override;
54 void buildInputSignals()
override;
55 void buildOutputSignals()
override;
58 llvm::SmallVector<sv::ReadInOutOp, 4> readers;
60 llvm::SmallVector<sv::AssignOp, 4> writers;
62 bool hasReaders() {
return !readers.empty(); }
63 bool hasWriters() {
return !writers.empty(); }
69 llvm::StringRef readSuffix;
71 llvm::StringRef writeSuffix;
76 llvm::StringRef readSuffix,
77 llvm::StringRef writeSuffix)
79 writeSuffix(writeSuffix) {}
81 LogicalResult HWInOutPortConversion::init() {
83 for (
auto *user : body->getArgument(origPort.argNum).getUsers()) {
84 if (
auto read = dyn_cast<sv::ReadInOutOp>(user))
85 readers.push_back(read);
86 else if (
auto write = dyn_cast<sv::AssignOp>(user))
87 writers.push_back(write);
89 return user->emitOpError() <<
"uses hw.inout port " << origPort.name
90 <<
" but the operation itself is unsupported.";
93 if (writers.size() > 1)
94 return converter.
getModule()->emitOpError()
95 <<
"multiple writers of inout port " << origPort.name
96 <<
" is unsupported.";
101 void HWInOutPortConversion::buildInputSignals() {
105 converter.createNewInput(origPort, readSuffix, origPort.type, readPort);
106 Value origInput = body->getArgument(origPort.argNum);
107 for (
auto *user : llvm::make_early_inc_range(origInput.getUsers())) {
112 read.replaceAllUsesWith(readValue);
120 converter.createNewOutput(origPort, writeSuffix, origPort.type,
126 void HWInOutPortConversion::buildOutputSignals() {
128 "`hw.inout` outputs not yet supported. Currently, `hw.inout` "
129 "outputs are handled by UntouchedPortConversion, given that "
130 "output `hw.inout` ports have a `ModulePort::Direction::Output` "
131 "direction instead of `ModulePort::Direction::InOut`. If this for "
132 "some reason changes, then this assert will fire.");
135 void HWInOutPortConversion::mapInputSignals(OpBuilder &b, Operation *inst,
137 SmallVectorImpl<Value> &newOperands,
138 ArrayRef<Backedge> newResults) {
143 newOperands[readPort.argNum] =
144 b.create<
ReadInOutOp>(inst->getLoc(), instValue).getResult();
150 Value writeFromInsideMod = newResults[
writePort.argNum];
151 b.create<
sv::AssignOp>(inst->getLoc(), instValue, writeFromInsideMod);
155 void HWInOutPortConversion::mapOutputSignals(
156 OpBuilder &b, Operation *inst, Value instValue,
157 SmallVectorImpl<Value> &newOperands, ArrayRef<Backedge> newResults) {
160 "`hw.inout` outputs not yet supported. Currently, `hw.inout` "
161 "outputs are handled by UntouchedPortConversion, given that "
162 "output `hw.inout` ports have a `ModulePort::Direction::Output` "
163 "direction instead of `ModulePort::Direction::InOut`. If this for "
164 "some reason changes, then this assert will fire.");
170 llvm::StringRef readSuffix,
171 llvm::StringRef writeSuffix)
173 writeSuffix(writeSuffix) {}
177 return {std::make_unique<HWInOutPortConversion>(converter, port,
178 readSuffix, writeSuffix)};
183 llvm::StringRef readSuffix;
184 llvm::StringRef writeSuffix;
189 void HWEliminateInOutPortsPass::runOnOperation() {
192 getAnalysis<circt::hw::InstanceGraph>();
193 llvm::DenseSet<InstanceGraphNode *> visited;
218 if (visited.count(node))
221 dyn_cast_or_null<hw::HWMutableModuleLike>(*node->getModule());
225 instanceGraph, mutableModule, readSuffix.getValue(),
226 writeSuffix.getValue())
228 return signalPassFailure();
234 const HWEliminateInOutPortsOptions &options) {
235 return std::make_unique<HWEliminateInOutPortsPass>(options);
assert(baseType &&"element must be base type")
static void writePort(uint16_t port)
Write the port number to a file.
HW-specific instance graph with a virtual entry node linking to all publicly visible modules.
virtual FailureOr< std::unique_ptr< PortConversion > > build(hw::PortInfo port)
Base class for the port conversion of a particular port.
hw::HWMutableModuleLike getModule()
LogicalResult run()
Run port conversion.
This is a Node in the InstanceGraph.
FailureOr< llvm::ArrayRef< InstanceGraphNode * > > getInferredTopLevelNodes()
Get the nodes corresponding to the inferred top-level modules of a circuit.
std::unique_ptr< mlir::Pass > createHWEliminateInOutPortsPass(const HWEliminateInOutPortsOptions &options={})
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
This holds the name, type, direction of a module's ports.