142 size_t portID,
const PortInfo &port,
bool isFlip,
143 Twine name,
FIRRTLType type, uint64_t fieldID,
144 const FieldIDSearch<hw::InnerSymAttr> &syms,
145 const FieldIDSearch<AnnotationSet> &annos) {
146 auto *ctx = type.getContext();
148 .
Case<BundleType>([&](BundleType bundle) -> LogicalResult {
151 if (conv != Convention::Scalarized && bundle.isPassive()) {
152 auto lastId = fieldID + bundle.getMaxFieldID();
154 {{StringAttr::get(ctx, name), type,
155 isFlip ? Direction::Out : Direction::In,
163 for (
auto [idx, elem] : llvm::enumerate(bundle.getElements())) {
165 mod, newPorts, conv, portID, port, isFlip ^ elem.isFlip,
166 name +
"_" + elem.
name.getValue(), elem.type,
167 fieldID + bundle.getFieldID(idx), syms, annos)))
169 if (!syms.empty(fieldID, fieldID))
170 return mod.emitError(
"Port [")
172 <<
"] should be subdivided, but cannot be because of "
174 << port.
sym.getSymIfExists(fieldID) <<
"] on a bundle";
175 if (!annos.empty(fieldID, fieldID)) {
176 auto err = mod.emitError(
"Port [")
178 <<
"] should be subdivided, but cannot be because of "
180 auto [b, e] = annos.find(fieldID, fieldID);
181 err << b->getClass() <<
"(" << b->getFieldID() <<
")";
184 err <<
", " << b->getClass() <<
"(" << b->getFieldID() <<
")";
185 err <<
"] on a bundle";
192 .Case<FVectorType>([&](FVectorType vector) -> LogicalResult {
193 if (conv != Convention::Scalarized &&
194 vector.getElementType().isPassive()) {
195 auto lastId = fieldID + vector.getMaxFieldID();
197 {{StringAttr::get(ctx, name), type,
198 isFlip ? Direction::Out : Direction::In,
206 for (
size_t i = 0, e = vector.getNumElements(); i < e; ++i) {
208 mod, newPorts, conv, portID, port, isFlip,
209 name +
"_" + Twine(i), vector.getElementType(),
210 fieldID + vector.getFieldID(i), syms, annos)))
212 if (!syms.empty(fieldID, fieldID))
213 return mod.emitError(
"Port [")
215 <<
"] should be subdivided, but cannot be because of "
217 << port.
sym.getSymIfExists(fieldID) <<
"] on a vector";
218 if (!annos.empty(fieldID, fieldID)) {
219 auto err = mod.emitError(
"Port [")
221 <<
"] should be subdivided, but cannot be because of "
223 auto [b, e] = annos.find(fieldID, fieldID);
224 err << b->getClass();
227 err <<
", " << b->getClass();
228 err <<
"] on a vector";
238 {{StringAttr::get(ctx, name), type,
239 isFlip ? Direction::Out : Direction::In,
267 ImplicitLocOpBuilder theBuilder(module.getLoc(), module.getContext());
272 DenseMap<size_t, size_t> domainMap;
273 for (
auto &newPort : newPorts) {
274 if (!type_isa<DomainType>(newPort.type))
276 domainMap[newPort.portID] = newPort.resultID;
278 for (
auto &newPort : newPorts) {
279 if (type_isa<DomainType>(newPort.type))
281 auto oldAssociations = dyn_cast_or_null<ArrayAttr>(newPort.domains);
282 if (!oldAssociations)
284 SmallVector<Attribute> newAssociations;
285 for (
auto oldAttr : oldAssociations)
286 newAssociations.push_back(theBuilder.getUI32IntegerAttr(
287 domainMap[cast<IntegerAttr>(oldAttr).getValue().getZExtValue()]));
288 newPort.domains = theBuilder.getArrayAttr(newAssociations);
291 if (
auto mod = dyn_cast<FModuleOp>(module.getOperation())) {
292 Block *body = mod.getBodyBlock();
293 theBuilder.setInsertionPointToStart(body);
294 auto oldNumArgs = body->getNumArguments();
299 SmallVector<Value> bounceWires(oldNumArgs);
300 for (
auto &p : newPorts) {
301 auto newArg = body->addArgument(p.type, p.loc);
304 if (p.fieldID != 0) {
305 auto &wire = bounceWires[p.portID];
307 wire = WireOp::create(theBuilder, module.getPortType(p.portID),
308 module.getPortNameAttr(p.portID),
309 NameKindEnum::InterestingName)
312 bounceWires[p.portID] = newArg;
317 for (
auto idx = 0U; idx < oldNumArgs; ++idx) {
318 if (!bounceWires[idx]) {
319 bounceWires[idx] = WireOp::create(theBuilder, module.getPortType(idx),
320 module.getPortNameAttr(idx))
323 body->getArgument(idx).replaceAllUsesWith(bounceWires[idx]);
327 body->eraseArguments(0, oldNumArgs);
330 for (
auto &p : newPorts) {
331 if (isa<BlockArgument>(bounceWires[p.portID]))
335 theBuilder, body->getArgument(p.resultID),
341 body->getArgument(p.resultID));
345 SmallVector<NamedAttribute, 8> newModuleAttrs;
348 for (
auto attr :
module->getAttrDictionary())
351 if (attr.getName() != "portNames" && attr.getName() != "portDirections" &&
352 attr.getName() != "portTypes" && attr.getName() != "portAnnotations" &&
353 attr.getName() != "portSymbols" && attr.getName() != "portLocations")
354 newModuleAttrs.push_back(attr);
356 SmallVector<Direction> newPortDirections;
357 SmallVector<Attribute> newPortNames;
358 SmallVector<Attribute> newPortTypes;
359 SmallVector<Attribute> newPortSyms;
360 SmallVector<Attribute> newPortLocations;
361 SmallVector<Attribute, 8> newPortAnnotations;
362 SmallVector<Attribute> newPortDomains;
364 for (
auto p : newPorts) {
365 newPortTypes.push_back(TypeAttr::get(p.type));
366 newPortNames.push_back(p.name);
367 newPortDirections.push_back(p.direction);
368 newPortSyms.push_back(p.sym);
369 newPortLocations.push_back(p.loc);
370 newPortAnnotations.push_back(p.annotations.getArrayAttr());
371 newPortDomains.push_back(p.domains ? p.domains : cache.aEmpty);
374 newModuleAttrs.push_back(NamedAttribute(
375 cache.sPortDirections,
378 newModuleAttrs.push_back(
379 NamedAttribute(cache.sPortNames, theBuilder.getArrayAttr(newPortNames)));
381 newModuleAttrs.push_back(
382 NamedAttribute(cache.sPortTypes, theBuilder.getArrayAttr(newPortTypes)));
384 newModuleAttrs.push_back(NamedAttribute(
385 cache.sPortLocations, theBuilder.getArrayAttr(newPortLocations)));
387 newModuleAttrs.push_back(NamedAttribute(
388 cache.sPortAnnotations, theBuilder.getArrayAttr(newPortAnnotations)));
390 newModuleAttrs.push_back(NamedAttribute(
391 cache.sPortDomains, theBuilder.getArrayAttr(newPortDomains)));
394 module->setAttrs(newModuleAttrs);
395 FModuleLike::fixupPortSymsArray(newPortSyms, theBuilder.getContext());
396 module.setPortSymbols(newPortSyms);
401 const DenseMap<StringAttr, PortConversion> &ports) {
402 auto fixupInstance = [&](
auto inst,
auto clone) ->
void {
403 ImplicitLocOpBuilder theBuilder(inst.getLoc(), inst);
407 StringAttr moduleName =
408 cast<StringAttr>(inst.getReferencedModuleNamesAttr()[0]);
410 const auto &modPorts = ports.at(moduleName);
413 SmallVector<PortInfo> instPorts;
414 for (
auto p : modPorts) {
418 instPorts.push_back(p);
421 auto newOp = clone(theBuilder, inst, instPorts);
423 auto oldDict = inst->getDiscardableAttrDictionary();
424 auto newDict = newOp->getDiscardableAttrDictionary();
425 auto oldNames = inst.getPortNamesAttr();
426 SmallVector<NamedAttribute> newAttrs;
427 for (
auto na : oldDict)
428 if (!newDict.contains(na.getName()))
429 newOp->setDiscardableAttr(na.getName(), na.getValue());
432 SmallVector<WireOp> bounce(inst.getNumResults());
433 for (
auto p : modPorts) {
435 if (p.fieldID == 0) {
436 inst.getResult(p.portID).replaceAllUsesWith(
437 newOp.getResult(p.resultID));
440 if (!bounce[p.portID]) {
441 bounce[p.portID] = WireOp::create(
442 theBuilder, inst.getResult(p.portID).getType(),
443 theBuilder.getStringAttr(
444 inst.getName() +
"." +
445 cast<StringAttr>(oldNames[p.portID]).getValue()));
446 inst.getResult(p.portID).replaceAllUsesWith(
447 bounce[p.portID].getResult());
451 emitConnect(theBuilder, newOp.getResult(p.resultID),
458 newOp.getResult(p.resultID));
462 for (
auto *use : llvm::make_early_inc_range(inst->getUsers())) {
463 assert(isa<MatchingConnectOp>(use) || isa<ConnectOp>(use));
470 mod->walk([&](Operation *op) ->
void {
471 TypeSwitch<Operation *>(op)
472 .Case<InstanceOp>([&](
auto inst) {
473 fixupInstance(inst, [&](ImplicitLocOpBuilder &theBuilder,
475 ArrayRef<PortInfo> newPorts) {
476 return InstanceOp::create(
477 theBuilder, newPorts, inst.getModuleName(), inst.getName(),
478 inst.getNameKind(), inst.getAnnotations().getValue(),
479 inst.getLayers(), inst.getLowerToBind(), inst.getDoNotPrint(),
480 inst.getInnerSymAttr());
483 .Case<InstanceChoiceOp>([&](
auto inst) {
484 fixupInstance(inst, [&](ImplicitLocOpBuilder &theBuilder,
485 InstanceChoiceOp inst,
486 ArrayRef<PortInfo> newPorts) {
487 return InstanceChoiceOp::create(
488 theBuilder, newPorts, inst.getModuleNamesAttr(),
489 inst.getCaseNamesAttr(), inst.getName(), inst.getNameKind(),
490 inst.getAnnotationsAttr(), inst.getLayersAttr(),
491 inst.getInnerSymAttr());
static std::unique_ptr< Context > context