143 size_t portID,
const PortInfo &port,
bool isFlip,
144 Twine name,
FIRRTLType type, uint64_t fieldID,
145 const FieldIDSearch<hw::InnerSymAttr> &syms,
146 const FieldIDSearch<AnnotationSet> &annos) {
147 auto *ctx = type.getContext();
149 .
Case<BundleType>([&](BundleType bundle) -> LogicalResult {
152 if (conv != Convention::Scalarized && bundle.isPassive()) {
153 auto lastId = fieldID + bundle.getMaxFieldID();
155 {{StringAttr::get(ctx, name), type,
156 isFlip ? Direction::Out : Direction::In,
164 for (
auto [idx, elem] : llvm::enumerate(bundle.getElements())) {
166 mod, newPorts, conv, portID, port, isFlip ^ elem.isFlip,
167 name +
"_" + elem.
name.getValue(), elem.type,
168 fieldID + bundle.getFieldID(idx), syms, annos)))
170 if (!syms.empty(fieldID, fieldID))
171 return mod.emitError(
"Port [")
173 <<
"] should be subdivided, but cannot be because of "
175 << port.
sym.getSymIfExists(fieldID) <<
"] on a bundle";
176 if (!annos.empty(fieldID, fieldID)) {
177 auto err = mod.emitError(
"Port [")
179 <<
"] should be subdivided, but cannot be because of "
181 auto [b, e] = annos.find(fieldID, fieldID);
182 err << b->getClass() <<
"(" << b->getFieldID() <<
")";
185 err <<
", " << b->getClass() <<
"(" << b->getFieldID() <<
")";
186 err <<
"] on a bundle";
193 .Case<FVectorType>([&](FVectorType vector) -> LogicalResult {
194 if (conv != Convention::Scalarized &&
195 vector.getElementType().isPassive()) {
196 auto lastId = fieldID + vector.getMaxFieldID();
198 {{StringAttr::get(ctx, name), type,
199 isFlip ? Direction::Out : Direction::In,
207 for (
size_t i = 0, e = vector.getNumElements(); i < e; ++i) {
209 mod, newPorts, conv, portID, port, isFlip,
210 name +
"_" + Twine(i), vector.getElementType(),
211 fieldID + vector.getFieldID(i), syms, annos)))
213 if (!syms.empty(fieldID, fieldID))
214 return mod.emitError(
"Port [")
216 <<
"] should be subdivided, but cannot be because of "
218 << port.
sym.getSymIfExists(fieldID) <<
"] on a vector";
219 if (!annos.empty(fieldID, fieldID)) {
220 auto err = mod.emitError(
"Port [")
222 <<
"] should be subdivided, but cannot be because of "
224 auto [b, e] = annos.find(fieldID, fieldID);
225 err << b->getClass();
228 err <<
", " << b->getClass();
229 err <<
"] on a vector";
239 {{StringAttr::get(ctx, name), type,
240 isFlip ? Direction::Out : Direction::In,
268 ImplicitLocOpBuilder theBuilder(module.getLoc(), module.getContext());
273 DenseMap<size_t, size_t> domainMap;
274 for (
auto &newPort : newPorts) {
275 if (!type_isa<DomainType>(newPort.type))
277 domainMap[newPort.portID] = newPort.resultID;
279 for (
auto &newPort : newPorts) {
280 if (type_isa<DomainType>(newPort.type))
282 auto oldAssociations = dyn_cast_or_null<ArrayAttr>(newPort.domains);
283 if (!oldAssociations)
285 SmallVector<Attribute> newAssociations;
286 for (
auto oldAttr : oldAssociations)
287 newAssociations.push_back(theBuilder.getUI32IntegerAttr(
288 domainMap[cast<IntegerAttr>(oldAttr).getValue().getZExtValue()]));
289 newPort.domains = theBuilder.getArrayAttr(newAssociations);
292 if (
auto mod = dyn_cast<FModuleOp>(module.getOperation())) {
293 Block *body = mod.getBodyBlock();
294 theBuilder.setInsertionPointToStart(body);
295 auto oldNumArgs = body->getNumArguments();
300 SmallVector<Value> bounceWires(oldNumArgs);
301 for (
auto &p : newPorts) {
302 auto newArg = body->addArgument(p.type, p.loc);
305 if (p.fieldID != 0) {
306 auto &wire = bounceWires[p.portID];
308 wire = WireOp::create(theBuilder, module.getPortType(p.portID),
309 module.getPortNameAttr(p.portID),
310 NameKindEnum::InterestingName)
313 bounceWires[p.portID] = newArg;
318 for (
auto idx = 0U; idx < oldNumArgs; ++idx) {
319 if (!bounceWires[idx]) {
320 bounceWires[idx] = WireOp::create(theBuilder, module.getPortType(idx),
321 module.getPortNameAttr(idx))
324 body->getArgument(idx).replaceAllUsesWith(bounceWires[idx]);
328 body->eraseArguments(0, oldNumArgs);
331 for (
auto &p : newPorts) {
332 if (isa<BlockArgument>(bounceWires[p.portID]))
336 theBuilder, body->getArgument(p.resultID),
342 body->getArgument(p.resultID));
346 SmallVector<NamedAttribute, 8> newModuleAttrs;
349 for (
auto attr :
module->getAttrDictionary())
352 if (attr.getName() != "portNames" && attr.getName() != "portDirections" &&
353 attr.getName() != "portTypes" && attr.getName() != "portAnnotations" &&
354 attr.getName() != "portSymbols" && attr.getName() != "portLocations")
355 newModuleAttrs.push_back(attr);
357 SmallVector<Direction> newPortDirections;
358 SmallVector<Attribute> newPortNames;
359 SmallVector<Attribute> newPortTypes;
360 SmallVector<Attribute> newPortSyms;
361 SmallVector<Attribute> newPortLocations;
362 SmallVector<Attribute, 8> newPortAnnotations;
363 SmallVector<Attribute> newPortDomains;
365 for (
auto p : newPorts) {
366 newPortTypes.push_back(TypeAttr::get(p.type));
367 newPortNames.push_back(p.name);
368 newPortDirections.push_back(p.direction);
369 newPortSyms.push_back(p.sym);
370 newPortLocations.push_back(p.loc);
371 newPortAnnotations.push_back(p.annotations.getArrayAttr());
372 newPortDomains.push_back(p.domains ? p.domains : cache.aEmpty);
375 newModuleAttrs.push_back(NamedAttribute(
376 cache.sPortDirections,
379 newModuleAttrs.push_back(
380 NamedAttribute(cache.sPortNames, theBuilder.getArrayAttr(newPortNames)));
382 newModuleAttrs.push_back(
383 NamedAttribute(cache.sPortTypes, theBuilder.getArrayAttr(newPortTypes)));
385 newModuleAttrs.push_back(NamedAttribute(
386 cache.sPortLocations, theBuilder.getArrayAttr(newPortLocations)));
388 newModuleAttrs.push_back(NamedAttribute(
389 cache.sPortAnnotations, theBuilder.getArrayAttr(newPortAnnotations)));
391 newModuleAttrs.push_back(NamedAttribute(
392 cache.sPortDomains, theBuilder.getArrayAttr(newPortDomains)));
395 module->setAttrs(newModuleAttrs);
396 FModuleLike::fixupPortSymsArray(newPortSyms, theBuilder.getContext());
397 module.setPortSymbols(newPortSyms);
402 const DenseMap<StringAttr, PortConversion> &ports) {
403 auto fixupInstance = [&](
auto inst,
auto clone) ->
void {
404 ImplicitLocOpBuilder theBuilder(inst.getLoc(), inst);
408 StringAttr moduleName =
409 cast<StringAttr>(inst.getReferencedModuleNamesAttr()[0]);
411 const auto &modPorts = ports.at(moduleName);
414 SmallVector<PortInfo> instPorts;
415 for (
auto p : modPorts) {
419 instPorts.push_back(p);
422 auto newOp = clone(theBuilder, inst, instPorts);
424 auto oldDict = inst->getDiscardableAttrDictionary();
425 auto newDict = newOp->getDiscardableAttrDictionary();
426 auto oldNames = inst.getPortNamesAttr();
427 SmallVector<NamedAttribute> newAttrs;
428 for (
auto na : oldDict)
429 if (!newDict.contains(na.getName()))
430 newOp->setDiscardableAttr(na.getName(), na.getValue());
433 SmallVector<WireOp> bounce(inst.getNumResults());
434 for (
auto p : modPorts) {
436 if (p.fieldID == 0) {
437 inst.getResult(p.portID).replaceAllUsesWith(
438 newOp.getResult(p.resultID));
441 if (!bounce[p.portID]) {
442 bounce[p.portID] = WireOp::create(
443 theBuilder, inst.getResult(p.portID).getType(),
444 theBuilder.getStringAttr(
445 inst.getName() +
"." +
446 cast<StringAttr>(oldNames[p.portID]).getValue()));
447 inst.getResult(p.portID).replaceAllUsesWith(
448 bounce[p.portID].getResult());
452 emitConnect(theBuilder, newOp.getResult(p.resultID),
459 newOp.getResult(p.resultID));
463 for (
auto *use : llvm::make_early_inc_range(inst->getUsers())) {
464 assert(isa<MatchingConnectOp>(use) || isa<ConnectOp>(use));
471 mod->walk([&](Operation *op) ->
void {
472 TypeSwitch<Operation *>(op)
473 .Case<InstanceOp>([&](
auto inst) {
474 fixupInstance(inst, [&](ImplicitLocOpBuilder &theBuilder,
476 ArrayRef<PortInfo> newPorts) {
477 return InstanceOp::create(
478 theBuilder, newPorts, inst.getModuleName(), inst.getName(),
479 inst.getNameKind(), inst.getAnnotations().getValue(),
480 inst.getLayers(), inst.getLowerToBind(), inst.getDoNotPrint(),
481 inst.getInnerSymAttr());
484 .Case<InstanceChoiceOp>([&](
auto inst) {
485 fixupInstance(inst, [&](ImplicitLocOpBuilder &theBuilder,
486 InstanceChoiceOp inst,
487 ArrayRef<PortInfo> newPorts) {
488 return InstanceChoiceOp::create(
489 theBuilder, newPorts, inst.getModuleNamesAttr(),
490 inst.getCaseNamesAttr(), inst.getName(), inst.getNameKind(),
491 inst.getAnnotationsAttr(), inst.getLayersAttr(),
492 inst.getInnerSymAttr());
static std::unique_ptr< Context > context