diff --git a/include/circt/Dialect/FIRRTL/FIRRTLAnnotationHelper.h b/include/circt/Dialect/FIRRTL/FIRRTLAnnotationHelper.h index 06408250882a..e6ef12422311 100644 --- a/include/circt/Dialect/FIRRTL/FIRRTLAnnotationHelper.h +++ b/include/circt/Dialect/FIRRTL/FIRRTLAnnotationHelper.h @@ -284,11 +284,18 @@ A tryGetAs(DictionaryAttr &dict, const Attribute &root, StringRef key, InstanceOp addPortsToModule( FModuleOp mod, InstanceOp instOnPath, FIRRTLType portType, Direction dir, StringRef newName, InstancePathCache &instancePathcache, - MLIRContext *context, llvm::function_ref getNamespace, - AnnoPathValue *instancePathToUpdate = nullptr, CircuitTargetCache *targetCaches = nullptr); +/// Add a port to each instance on the path `instancePath` and forward the +/// `fromVal` through them. It returns the port added to the last module on the +/// given path. The module referenced by the first instance on the path must +/// contain `fromVal`. +Value borePortsOnPath( + SmallVector &instancePath, FModuleOp lcaModule, Value fromVal, + StringRef newNameHint, InstancePathCache &instancePathcache, + llvm::function_ref getNamespace, + CircuitTargetCache *targetCachesInstancePathCache); } // namespace firrtl } // namespace circt diff --git a/lib/Dialect/FIRRTL/FIRRTLAnnotationHelper.cpp b/lib/Dialect/FIRRTL/FIRRTLAnnotationHelper.cpp index a2c6b7e6c743..bf71795c8698 100644 --- a/lib/Dialect/FIRRTL/FIRRTLAnnotationHelper.cpp +++ b/lib/Dialect/FIRRTL/FIRRTLAnnotationHelper.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "circt/Dialect/FIRRTL/FIRRTLAnnotationHelper.h" +#include "mlir/IR/ImplicitLocOpBuilder.h" using namespace circt; using namespace firrtl; @@ -315,14 +316,13 @@ Optional firrtl::resolvePath(StringRef rawPath, InstanceOp firrtl::addPortsToModule( FModuleOp mod, InstanceOp instOnPath, FIRRTLType portType, Direction dir, StringRef newName, InstancePathCache &instancePathcache, - MLIRContext *context, llvm::function_ref getNamespace, - AnnoPathValue *instancePathToUpdate, CircuitTargetCache *targetCaches) { + CircuitTargetCache *targetCaches) { // To store the cloned version of `instOnPath`. InstanceOp clonedInstOnPath; // Get a new port name from the Namespace. auto portName = [&](FModuleOp nameForMod) { - return StringAttr::get(context, + return StringAttr::get(nameForMod.getContext(), getNamespace(nameForMod).newName("_gen_" + newName)); }; // The port number for the new port. @@ -341,17 +341,82 @@ InstanceOp firrtl::addPortsToModule( instancePathcache.replaceInstance(useInst, clonedInst); if (targetCaches) targetCaches->replaceOp(useInst, clonedInst); - if (instancePathToUpdate) { - auto *iter = llvm::find(instancePathToUpdate->instances, useInst); - if (iter != instancePathToUpdate->instances.end()) - *iter = clonedInst; - } useInst->replaceAllUsesWith(clonedInst.getResults().drop_back()); useInst->erase(); } return clonedInstOnPath; } +Value firrtl::borePortsOnPath( + SmallVector &instancePath, FModuleOp lcaModule, Value fromVal, + StringRef newNameHint, InstancePathCache &instancePathcache, + llvm::function_ref getNamespace, + CircuitTargetCache *targetCachesInstancePathCache) { + // Create connections of the `fromVal` by adding ports through all the + // instances of `instancePath`. `instancePath` specifies a path from a source + // module through the lcaModule till a target module. source module is the + // parent module of `fromval` and target module is the referenced target + // module of the last instance in the instancePath. + + // If instancePath empty then just return the `fromVal`. + if (instancePath.empty()) + return fromVal; + + FModuleOp srcModule; + if (auto block = fromVal.dyn_cast()) + srcModule = cast(block.getOwner()->getParentOp()); + else + srcModule = fromVal.getDefiningOp()->getParentOfType(); + + // If the `srcModule` is the `lcaModule`, then we only need to drill input + // ports starting from the `lcaModule` till the end of `instancePath`. For all + // other cases, we start to drill output ports from the `srcModule` till the + // `lcaModule`, and then input ports from `lcaModule` till the end of + // `instancePath`. + Direction dir = Direction::Out; + if (srcModule == lcaModule) + dir = Direction::In; + + auto valType = fromVal.getType().cast(); + auto forwardVal = fromVal; + for (auto instOnPath : instancePath) { + auto referencedModule = cast( + instancePathcache.instanceGraph.getReferencedModule(instOnPath)); + unsigned portNo = referencedModule.getNumPorts(); + // Add a new port to referencedModule, and all its uses/instances. + InstanceOp clonedInst = addPortsToModule( + referencedModule, instOnPath, valType, dir, newNameHint, + instancePathcache, getNamespace, targetCachesInstancePathCache); + // `instOnPath` will be erased and replaced with `clonedInst`. So, there + // should be no more use of `instOnPath`. + auto clonedInstRes = clonedInst.getResult(portNo); + auto referencedModNewPort = referencedModule.getArgument(portNo); + // If out direction, then connect `forwardVal` to the `referencedModNewPort` + // (the new port of referenced module) else set the new input port of the + // cloned instance with `forwardVal`. If out direction, then set the + // `forwardVal` to the result of the cloned instance, else set the + // `forwardVal` to the new port of the referenced module. + if (dir == Direction::Out) { + auto builder = ImplicitLocOpBuilder::atBlockEnd( + forwardVal.getLoc(), forwardVal.isa() + ? referencedModule.getBodyBlock() + : forwardVal.getDefiningOp()->getBlock()); + builder.create(referencedModNewPort, forwardVal); + forwardVal = clonedInstRes; + } else { + auto builder = ImplicitLocOpBuilder::atBlockEnd(clonedInst.getLoc(), + clonedInst->getBlock()); + builder.create(clonedInstRes, forwardVal); + forwardVal = referencedModNewPort; + } + + // Switch direction of reached the `lcaModule`. + if (clonedInst->getParentOfType() == lcaModule) + dir = Direction::In; + } + return forwardVal; +} + //===----------------------------------------------------------------------===// // AnnoTargetCache //===----------------------------------------------------------------------===//