17static StringAttr
append(StringAttr base,
const Twine &suffix) {
18 if (suffix.isTriviallyEmpty())
20 auto *
context = base.getContext();
21 return StringAttr::get(
context, base.getValue() + suffix);
34 isUntouchedFlag =
true;
38 SmallVectorImpl<Value> &newOperands,
39 ArrayRef<Backedge> newResults)
override {
40 newOperands[portInfo.argNum] = instValue;
43 SmallVectorImpl<Value> &newOperands,
44 ArrayRef<Backedge> newResults)
override {
45 instValue.replaceAllUsesWith(newResults[portInfo.argNum]);
50 Value newValue = converter.createNewInput(
51 origPort,
"", origPort.type, portInfo, PortAttrPolicy::Preserve);
53 body->getArgument(origPort.argNum).replaceAllUsesWith(newValue);
59 output = body->getTerminator()->getOperand(origPort.argNum);
60 converter.createNewOutput(origPort,
"", origPort.type, output, portInfo,
61 PortAttrPolicy::Preserve);
69FailureOr<std::unique_ptr<PortConversion>>
73 return {std::make_unique<UntouchedPortConversion>(
converter, port)};
77 : moduleNode(moduleNode), b(moduleNode->getModule()->getContext()) {
79 assert(
mod &&
"PortConverter only works on HWMutableModuleLike");
81 if (
mod->getNumRegions() == 1 &&
mod->getRegion(0).hasOneBlock()) {
82 body = &
mod->getRegion(0).front();
102 return body->addArgument(type, origPort.
loc);
106 Type type, Value output,
122 OpBuilder::InsertionGuard g(
b);
123 b.setInsertionPointToStart(
body);
130 bool foundLoweredPorts =
false;
132 auto createPortLowering = [&](
PortInfo port) {
137 auto loweredPort =
ssb->build(port);
138 if (failed(loweredPort))
141 foundLoweredPorts |= !(*loweredPort)->isUntouched();
142 loweredPorts.emplace_back(std::move(*loweredPort));
144 if (failed(loweredPorts.back()->init()))
152 if (failed(createPortLowering(port)))
156 if (!foundLoweredPorts) {
166 lowering->lowerPort();
168 lowering->lowerPort();
174 SmallVector<unsigned> inputsToErase(
mod.getNumInputPorts());
175 std::iota(inputsToErase.begin(), inputsToErase.end(), 0);
176 SmallVector<unsigned> outputsToErase(
mod.getNumOutputPorts());
177 std::iota(outputsToErase.begin(), outputsToErase.end(), 0);
184 body->eraseArguments([&ports](BlockArgument arg) {
185 return arg.getArgNumber() < ports.
sizeInputs();
194 auto instanceLike = instance->getInstance<hw::HWInstanceLike>();
197 hw::InstanceOp hwInstance = dyn_cast_or_null<hw::InstanceOp>(*instanceLike);
199 return instanceLike->emitOpError(
200 "This code only converts hw.instance instances - ask your friendly "
201 "neighborhood compiler engineers to implement support for something "
202 "like an hw::HWMutableInstanceLike interface");
214 ImplicitLocOpBuilder
b(inst.getLoc(), inst);
220 SmallVector<Backedge> newResults;
222 newResults.push_back(beb.
get(outputPort.type));
225 SmallVector<Value> newOperands(ports.
sizeInputs(), {});
226 for (
size_t oldOpIdx = 0, e = inst.getNumOperands(); oldOpIdx < e; ++oldOpIdx)
228 b, inst, inst->getOperand(oldOpIdx), newOperands, newResults);
231 for (
size_t oldResIdx = 0, e = inst.getNumResults(); oldResIdx < e;
234 b, inst, inst->getResult(oldResIdx), newOperands, newResults);
238 assert(llvm::none_of(newOperands, [](Value v) {
return !v; }));
239 b.setInsertionPointAfter(inst);
241 InstanceOp::create(
b,
mod, inst.getInstanceNameAttr(), newOperands,
242 inst.getParameters(), inst.getInnerSymAttr());
243 newInst->setDialectAttrs(inst->getDialectAttrs());
244 if (
auto doNotPrint = inst.getDoNotPrintAttr())
245 newInst.setDoNotPrintAttr(doNotPrint);
248 for (
auto [idx, be] : llvm::enumerate(newResults))
249 be.setValue(newInst.getResult(idx));
assert(baseType &&"element must be base type")
static std::unique_ptr< Context > context
static StringAttr append(StringAttr base, const Twine &suffix)
Return a attribute with the specified suffix appended.
Instantiate one of these and use it to build typed backedges.
Backedge get(mlir::Type resultType, mlir::LocationAttr optionalLoc={})
Create a typed backedge.
PortConverterImpl & converter
virtual FailureOr< std::unique_ptr< PortConversion > > build(hw::PortInfo port)
Base class for the port conversion of a particular port.
virtual void buildInputSignals()=0
virtual void mapInputSignals(OpBuilder &b, Operation *inst, Value instValue, SmallVectorImpl< Value > &newOperands, ArrayRef< Backedge > newResults)=0
Update an instance port to the new port information.
virtual void mapOutputSignals(OpBuilder &b, Operation *inst, Value instValue, SmallVectorImpl< Value > &newOperands, ArrayRef< Backedge > newResults)=0
virtual void buildOutputSignals()=0
void createNewOutput(hw::PortInfo origPort, const Twine &suffix, Type type, Value output, hw::PortInfo &newPort, PortAttrPolicy attrPolicy=PortAttrPolicy::Drop)
Same as above.
LogicalResult run()
Run port conversion.
SmallVector< std::unique_ptr< PortConversion > > loweredOutputs
SmallVector< std::pair< unsigned, hw::PortInfo >, 0 > newInputs
igraph::InstanceGraphNode * moduleNode
Value createNewInput(hw::PortInfo origPort, const Twine &suffix, Type type, hw::PortInfo &newPort, PortAttrPolicy attrPolicy=PortAttrPolicy::Drop)
These two methods take care of allocating new ports in the correct place based on the position of 'or...
SmallVector< std::unique_ptr< PortConversion > > loweredInputs
hw::HWMutableModuleLike mod
void updateInstance(hw::InstanceOp)
Updates an instance of the module.
std::unique_ptr< PortConversionBuilder > ssb
PortConverterImpl(igraph::InstanceGraphNode *moduleNode)
SmallVector< std::pair< unsigned, hw::PortInfo >, 0 > newOutputs
This is a Node in the InstanceGraph.
llvm::iterator_range< UseIterator > uses()
auto getModule()
Get the module that this node is tracking.
PortAttrPolicy
Controls whether a newly created port inherits the original port's attributes.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
This holds a decoded list of input/inout and output ports for a module or instance.
size_t sizeOutputs() const
size_t sizeInputs() const
PortDirectionRange getOutputs()
This holds the name, type, direction of a module's ports.
DictionaryAttr attrs
The optional symbol for this port.