11#include "mlir/Pass/Pass.h"
20#include "mlir/Transforms/DialectConversion.h"
24#define GEN_PASS_DEF_KANAGAWACONTAINERIZE
25#include "circt/Dialect/Kanagawa/KanagawaPasses.h.inc"
35 OutlineContainerPattern(MLIRContext *
context, Namespace &ns)
36 : OpConversionPattern<ContainerOp>(
context), ns(ns) {}
38 using OpAdaptor =
typename OpConversionPattern<ContainerOp>::OpAdaptor;
41 matchAndRewrite(ContainerOp op, OpAdaptor adaptor,
42 ConversionPatternRewriter &rewriter)
const override {
46 dyn_cast_or_null<ClassOp>(op.getOperation()->getParentOp());
47 assert(parentClass &&
"This pattern should never be called on a container"
48 "that is not nested within a class.");
49 [[maybe_unused]]
auto design = parentClass.getParentOp<DesignOp>();
50 assert(design &&
"Parent class should be nested within a design.");
52 rewriter.setInsertionPoint(parentClass);
53 StringAttr newContainerName = rewriter.getStringAttr(
54 ns.newName(parentClass.getInnerNameAttr().strref() +
"_" +
55 op.getInnerNameAttr().strref()));
56 auto newContainer = ContainerOp::create(
57 rewriter, op.getLoc(), newContainerName,
false);
59 rewriter.mergeBlocks(op.getBodyBlock(), newContainer.getBodyBlock(), {});
62 rewriter.setInsertionPoint(op);
63 ContainerInstanceOp::create(rewriter, parentClass.getLoc(),
64 hw::InnerSymAttr::get(newContainerName),
65 newContainer.getInnerRef());
74 using OpConversionPattern<ClassOp>::OpConversionPattern;
77 matchAndRewrite(ClassOp op, OpAdaptor adaptor,
78 ConversionPatternRewriter &rewriter)
const override {
81 ContainerOp::create(rewriter, op.getLoc(), op.getInnerSymAttr(),
82 false, op.getNameAttr());
83 rewriter.mergeBlocks(op.getBodyBlock(), newContainer.getBodyBlock(), {});
89struct InstanceToContainerInstancePattern
91 using OpConversionPattern<InstanceOp>::OpConversionPattern;
94 matchAndRewrite(InstanceOp op, OpAdaptor adaptor,
95 ConversionPatternRewriter &rewriter)
const override {
97 rewriter.replaceOpWithNewOp<ContainerInstanceOp>(op, op.getInnerSym(),
98 op.getTargetNameAttr());
104struct ContainerizePass
105 :
public circt::kanagawa::impl::KanagawaContainerizeBase<ContainerizePass> {
106 void runOnOperation()
override;
110 LogicalResult outlineContainers();
113 LogicalResult containerizeClasses();
117LogicalResult ContainerizePass::outlineContainers() {
119 ConversionTarget target(*
context);
120 target.addLegalDialect<KanagawaDialect>();
121 target.addDynamicallyLegalOp<ContainerOp>(
122 [&](
auto *op) {
return !isa<kanagawa::ClassOp>(op->getParentOp()); });
123 RewritePatternSet patterns(
context);
127 SymbolCache symCache;
129 getOperation(), [&](StringAttr name,
const hw::InnerSymTarget &target) {
137 patterns.insert<OutlineContainerPattern>(
context, ns);
138 return applyPartialConversion(getOperation(), target, std::move(patterns));
141LogicalResult ContainerizePass::containerizeClasses() {
143 ConversionTarget target(*
context);
144 target.addLegalDialect<KanagawaDialect>();
145 target.addIllegalOp<ClassOp, InstanceOp>();
146 RewritePatternSet patterns(
context);
147 patterns.insert<ClassToContainerPattern, InstanceToContainerInstancePattern>(
149 return applyPartialConversion(getOperation(), target, std::move(patterns));
152void ContainerizePass::runOnOperation() {
153 if (failed(outlineContainers()) || failed(containerizeClasses()))
158 return std::make_unique<ContainerizePass>();
assert(baseType &&"element must be base type")
static std::unique_ptr< Context > context
void add(mlir::ModuleOp module)
void addDefinitions(mlir::Operation *top)
Populate the symbol cache with all symbol-defining operations within the 'top' operation.
void addDefinition(mlir::Attribute key, mlir::Operation *op) override
In the building phase, add symbols.
Operation * getOp() const
Return the target's base operation. For ports, this is the module.
static RetTy walkSymbols(Operation *op, FuncTy &&callback)
Walk the given IST operation and invoke the callback for all encountered inner symbols.
std::unique_ptr< mlir::Pass > createContainerizePass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.