21 #include "mlir/IR/BuiltinOps.h"
22 #include "mlir/IR/IRMapping.h"
23 #include "mlir/IR/PatternMatch.h"
24 #include "mlir/IR/Threading.h"
25 #include "mlir/Support/LogicalResult.h"
26 #include "mlir/Transforms/DialectConversion.h"
27 #include "llvm/ADT/STLExtras.h"
28 #include "llvm/Support/raw_ostream.h"
31 using namespace circt;
41 PathInfo(Operation *op, FlatSymbolRefAttr symRef) : op(op), symRef(symRef) {
42 assert(op &&
"op must not be null");
43 assert(symRef &&
"symRef must not be null");
46 operator bool()
const {
return op !=
nullptr; }
48 Operation *op =
nullptr;
49 FlatSymbolRefAttr symRef =
nullptr;
53 using PathInfoTable = DenseMap<DistinctAttr, PathInfo>;
56 static constexpr StringRef kClassNameSuffix =
"_Class";
67 struct ClassLoweringState {
68 FModuleLike moduleLike;
69 om::ClassLike classLike;
72 struct LowerClassesPass :
public LowerClassesBase<LowerClassesPass> {
73 void runOnOperation()
override;
76 LogicalResult lowerPaths(PathInfoTable &pathInfoTable,
77 SymbolTable &symbolTable);
80 bool shouldCreateClass(FModuleLike moduleLike);
83 ClassLoweringState createClass(FModuleLike moduleLike);
86 void lowerClassLike(ClassLoweringState state);
87 void lowerClass(om::ClassOp classOp, FModuleLike moduleLike);
88 void lowerClassExtern(ClassExternOp classExternOp, FModuleLike moduleLike);
91 LogicalResult updateInstances(Operation *op,
InstanceGraph &instanceGraph,
92 SymbolTable &symbolTable);
95 LogicalResult dialectConversion(
96 Operation *op,
const PathInfoTable &pathInfoTable,
97 const DenseMap<StringAttr, firrtl::ClassType> &classTypeTable);
108 LogicalResult LowerClassesPass::lowerPaths(PathInfoTable &pathInfoTable,
109 SymbolTable &symbolTable) {
110 auto *context = &getContext();
111 auto circuit = getOperation();
112 hw::InnerSymbolNamespaceCollection namespaces;
115 auto processPathTrackers = [&](
AnnoTarget target) -> LogicalResult {
117 auto annotations = target.getAnnotations();
118 auto *op = target.getOp();
120 annotations.removeAnnotations([&](
Annotation anno) {
126 if (!anno.
isClass(
"circt.tracker"))
130 auto id = anno.
getMember<DistinctAttr>(
"id");
132 op->emitError(
"circt.tracker annotation missing id field");
144 {portTarget.getPortNo(), portTarget.getOp(), fieldID},
145 [&](FModuleLike module) -> hw::InnerSymbolNamespace & {
146 return namespaces[module];
148 }
else if (
auto module = dyn_cast<FModuleLike>(op)) {
149 assert(!fieldID &&
"field not valid for modules");
153 {target.getOp(), fieldID},
154 [&](FModuleLike module) -> hw::InnerSymbolNamespace & {
155 return namespaces[module];
160 SmallVector<Attribute> path;
161 if (
auto hierName = anno.
getMember<FlatSymbolRefAttr>(
"circt.nonlocal")) {
163 dyn_cast<hw::HierPathOp>(symbolTable.lookup(hierName.getAttr()));
165 op->emitError(
"annotation does not point at a HierPathOp");
170 auto oldPath = hierPathOp.getNamepath().getValue();
171 llvm::append_range(path, oldPath.drop_back());
173 path.push_back(targetSym);
177 auto &pathInfo = pathInfoTable[id];
180 emitError(pathInfo.op->getLoc(),
"duplicate identifier found");
181 diag.attachNote(op->getLoc()) <<
"other identifier here";
187 pathInfo = {op, cache.getRefFor(pathAttr)};
195 target.setAnnotations(annotations);
199 for (
auto module : circuit.getOps<FModuleLike>()) {
204 for (
unsigned i = 0, e = module.getNumPorts(); i < e; ++i)
208 auto result = module.walk([&](hw::InnerSymbolOpInterface op) {
210 return WalkResult::interrupt();
211 return WalkResult::advance();
213 if (result.wasInterrupted())
220 void LowerClassesPass::runOnOperation() {
221 MLIRContext *ctx = &getContext();
224 CircuitOp circuit = getOperation();
228 SymbolTable &symbolTable = getAnalysis<SymbolTable>();
231 PathInfoTable pathInfoTable;
232 if (failed(lowerPaths(pathInfoTable, symbolTable))) {
238 DenseMap<StringAttr, firrtl::ClassType> classTypeTable;
239 SmallVector<ClassLoweringState> loweringState;
240 for (
auto moduleLike : circuit.getOps<FModuleLike>()) {
241 if (shouldCreateClass(moduleLike)) {
242 loweringState.push_back(createClass(moduleLike));
244 dyn_cast<firrtl::ClassLike>(moduleLike.getOperation()))
245 classTypeTable[classLike.getNameAttr()] = classLike.getInstanceType();
250 mlir::parallelForEach(ctx, loweringState,
251 [
this](
auto state) { lowerClassLike(state); });
254 for (
auto state : loweringState) {
255 if (isa<firrtl::ClassLike>(state.moduleLike.getOperation()))
256 state.moduleLike.erase();
260 SmallVector<Operation *> objectContainers;
261 for (
auto &op : circuit.getOps())
262 if (isa<FModuleOp, om::ClassLike>(op))
263 objectContainers.push_back(&op);
266 if (failed(mlir::failableParallelForEach(
267 ctx, objectContainers,
268 [
this, &instanceGraph, &symbolTable](
auto *op) {
269 return updateInstances(op, instanceGraph, symbolTable);
271 return signalPassFailure();
275 mlir::failableParallelForEach(ctx, objectContainers, [&](
auto *op) {
276 return dialectConversion(op, pathInfoTable, classTypeTable);
278 return signalPassFailure();
281 markAnalysesPreserved<InstanceGraph>();
285 return std::make_unique<LowerClassesPass>();
289 bool LowerClassesPass::shouldCreateClass(FModuleLike moduleLike) {
290 if (isa<firrtl::ClassLike>(moduleLike.getOperation()))
294 if (moduleLike.isPublic())
297 return llvm::any_of(moduleLike.getPorts(), [](
PortInfo port) {
298 return isa<PropertyType>(port.type);
303 ClassLoweringState LowerClassesPass::createClass(FModuleLike moduleLike) {
305 SmallVector<StringRef> formalParamNames;
307 formalParamNames.emplace_back(
"basepath");
308 for (
auto [index, port] : llvm::enumerate(moduleLike.getPorts()))
309 if (port.isInput() && isa<PropertyType>(port.type))
310 formalParamNames.push_back(port.name);
312 OpBuilder
builder = OpBuilder::atBlockEnd(getOperation().getBodyBlock());
315 StringRef className = moduleLike.getName();
318 if (
auto externMod = dyn_cast<FExtModuleOp>(moduleLike.getOperation()))
319 if (
auto defname = externMod.getDefname())
320 className = defname.value();
325 isa<FModuleOp, FExtModuleOp>(moduleLike) ? kClassNameSuffix :
"";
328 om::ClassLike loweredClassOp;
329 if (isa<firrtl::ExtClassOp, firrtl::FExtModuleOp>(moduleLike.getOperation()))
330 loweredClassOp =
builder.create<om::ClassExternOp>(
331 moduleLike.getLoc(), className + suffix, formalParamNames);
333 loweredClassOp =
builder.create<om::ClassOp>(
334 moduleLike.getLoc(), className + suffix, formalParamNames);
336 return {moduleLike, loweredClassOp};
339 void LowerClassesPass::lowerClassLike(ClassLoweringState state) {
340 auto moduleLike = state.moduleLike;
341 auto classLike = state.classLike;
343 if (
auto classOp = dyn_cast<om::ClassOp>(classLike.getOperation())) {
344 return lowerClass(classOp, moduleLike);
346 if (
auto classExternOp =
347 dyn_cast<om::ClassExternOp>(classLike.getOperation())) {
348 return lowerClassExtern(classExternOp, moduleLike);
350 llvm_unreachable(
"unhandled class-like op");
353 void LowerClassesPass::lowerClass(om::ClassOp classOp, FModuleLike moduleLike) {
358 SmallVector<Property> inputProperties;
359 BitVector portsToErase(moduleLike.getNumPorts());
360 for (
auto [index, port] : llvm::enumerate(moduleLike.getPorts())) {
362 if (!isa<PropertyType>(port.type))
367 inputProperties.push_back({index, port.name, port.type, port.loc});
370 portsToErase.set(index);
375 Block *classBody = &classOp->getRegion(0).emplaceBlock();
379 for (
auto inputProperty : inputProperties) {
380 BlockArgument parameterValue =
381 classBody->addArgument(inputProperty.type, inputProperty.loc);
382 BlockArgument inputValue =
383 moduleLike->getRegion(0).getArgument(inputProperty.index);
384 mapping.map(inputValue, parameterValue);
388 SmallVector<Operation *> opsToErase;
389 OpBuilder
builder = OpBuilder::atBlockBegin(classOp.getBodyBlock());
390 for (
auto &op : moduleLike->getRegion(0).getOps()) {
392 auto propertyOperands = llvm::any_of(op.getOperandTypes(), [](Type type) {
393 return isa<PropertyType>(type);
397 auto propertyResults = llvm::any_of(
398 op.getResultTypes(), [](Type type) { return isa<PropertyType>(type); });
401 if (!propertyOperands && !propertyResults)
409 if (!isa<InstanceOp>(op))
410 opsToErase.push_back(&op);
414 for (
auto op : llvm::make_early_inc_range(classOp.getOps<PropAssignOp>())) {
417 auto outputPort = dyn_cast<BlockArgument>(op.getDest());
422 auto name = moduleLike.getPortName(outputPort.getArgNumber());
423 builder.create<ClassFieldOp>(op.getLoc(), name, op.getSrc());
429 if (!isa<firrtl::ClassLike>(moduleLike.getOperation())) {
431 for (
auto *op : llvm::reverse(opsToErase))
435 moduleLike.erasePorts(portsToErase);
439 void LowerClassesPass::lowerClassExtern(ClassExternOp classExternOp,
440 FModuleLike moduleLike) {
444 BitVector portsToErase(moduleLike.getNumPorts());
445 Block *classBody = &classExternOp.getRegion().emplaceBlock();
446 OpBuilder
builder = OpBuilder::atBlockBegin(classBody);
452 for (
unsigned i = 0, e = moduleLike.getNumPorts(); i < e; ++i) {
453 auto type = moduleLike.getPortType(i);
454 if (!isa<PropertyType>(type))
457 auto loc = moduleLike.getPortLocation(i);
458 auto direction = moduleLike.getPortDirection(i);
459 if (direction == Direction::In)
460 classBody->addArgument(type, loc);
462 auto name = moduleLike.getPortNameAttr(i);
463 builder.create<om::ClassExternFieldOp>(loc, name, type);
472 if (!isa<firrtl::ClassLike>(moduleLike.getOperation())) {
474 moduleLike.erasePorts(portsToErase);
482 SmallVectorImpl<Operation *> &opsToErase) {
484 auto basePath = firrtlObject->getBlock()->getArgument(0);
487 auto firrtlClassType = firrtlObject.getType();
488 auto numElements = firrtlClassType.getNumElements();
489 llvm::SmallVector<unsigned> argIndexTable;
492 unsigned nextArgIndex = 1;
495 auto direction = firrtlClassType.getElement(i).direction;
496 if (direction == Direction::In)
497 argIndexTable[i] = nextArgIndex++;
503 llvm::SmallVector<Value> args;
504 args.resize(nextArgIndex);
507 for (
auto *user : llvm::make_early_inc_range(firrtlObject->getUsers())) {
508 if (
auto subfield = dyn_cast<ObjectSubfieldOp>(user)) {
509 auto index = subfield.getIndex();
510 auto direction = firrtlClassType.getElement(index).direction;
514 if (direction == Direction::Out)
517 for (
auto *subfieldUser :
518 llvm::make_early_inc_range(subfield->getUsers())) {
519 if (
auto propassign = dyn_cast<PropAssignOp>(subfieldUser)) {
523 auto dst = propassign.getOperand(0);
524 auto src = propassign.getOperand(1);
525 if (dst == subfield.getResult()) {
526 args[argIndexTable[index]] = src;
527 opsToErase.push_back(propassign);
532 opsToErase.push_back(subfield);
538 auto element = firrtlClassType.getElement(i);
539 if (element.direction == Direction::Out)
542 auto argIndex = argIndexTable[i];
544 return emitError(firrtlObject.getLoc())
545 <<
"uninitialized input port " << element.name;
549 auto className = firrtlObject.getType().getNameAttr();
553 builder.setInsertionPoint(firrtlObject);
554 auto object =
builder.create<om::ObjectOp>(
555 firrtlObject.getLoc(), classType, firrtlObject.getClassNameAttr(), args);
559 firrtlObject.replaceAllUsesWith(
object.getResult());
562 opsToErase.push_back(firrtlObject);
572 SmallVectorImpl<Operation *> &opsToErase,
573 SymbolTable &symbolTable) {
577 SmallVector<Value> actualParameters;
579 actualParameters.push_back(firrtlInstance->getBlock()->getArgument(0));
580 for (
auto result : firrtlInstance.getResults()) {
582 if (firrtlInstance.getPortDirection(result.getResultNumber()) ==
587 auto propertyResult = dyn_cast<FIRRTLPropertyValue>(result);
594 assert(propertyAssignment &&
"properties require single assignment");
595 actualParameters.push_back(propertyAssignment.getSrc());
598 opsToErase.push_back(propertyAssignment);
602 auto referencedModule =
603 dyn_cast<FModuleLike>(firrtlInstance.getReferencedModule(symbolTable));
605 StringRef moduleName = referencedModule.getName();
608 if (
auto externMod = dyn_cast<FExtModuleOp>(referencedModule.getOperation()))
609 if (
auto defname = externMod.getDefname())
610 moduleName = defname.value();
614 builder.getStringAttr(moduleName + kClassNameSuffix));
619 builder.setInsertionPoint(firrtlInstance);
621 builder.create<om::ObjectOp>(firrtlInstance.getLoc(), classType,
622 className.getAttr(), actualParameters);
627 for (
auto result : firrtlInstance.getResults()) {
629 if (firrtlInstance.getPortDirection(result.getResultNumber()) !=
634 if (!isa<PropertyType>(result.getType()))
639 firrtlInstance.getPortName(result.getResultNumber()))});
642 auto objectField =
builder.create<ObjectFieldOp>(
643 object.getLoc(), result.getType(), object, objectFieldPath);
645 result.replaceAllUsesWith(objectField);
649 opsToErase.push_back(firrtlInstance);
658 SmallVectorImpl<Operation *> &opsToErase,
661 BitVector portsToErase(firrtlInstance.getNumResults());
662 for (
auto result : firrtlInstance.getResults())
663 if (isa<PropertyType>(result.getType()))
664 portsToErase.set(result.getResultNumber());
667 if (portsToErase.none())
671 builder.setInsertionPoint(firrtlInstance);
672 InstanceOp newInstance = firrtlInstance.erasePorts(
builder, portsToErase);
681 opsToErase.push_back(firrtlInstance);
687 LogicalResult LowerClassesPass::updateInstances(Operation *op,
689 SymbolTable &symbolTable) {
695 SmallVector<Operation *> opsToErase;
698 for (
auto &instance : llvm::make_early_inc_range(op->getRegion(0).getOps())) {
699 LogicalResult result =
700 TypeSwitch<Operation *, LogicalResult>(&instance)
701 .Case([&](firrtl::ObjectOp firrtlObject) {
705 .Case([&](InstanceOp firrtlInstance) {
706 return TypeSwitch<Operation *, LogicalResult>(op)
707 .Case([&](om::ClassLike) {
711 opsToErase, symbolTable);
713 .Case([&](FModuleOp) {
717 firrtlInstance,
builder, opsToErase, instanceGraph);
719 .Default([](
auto *op) {
return success(); });
721 .Default([](
auto *op) {
return success(); });
728 for (
auto *op : opsToErase)
738 using OpConversionPattern::OpConversionPattern;
742 ConversionPatternRewriter &rewriter)
const override {
743 rewriter.replaceOpWithNewOp<om::ConstantOp>(
751 using OpConversionPattern::OpConversionPattern;
755 ConversionPatternRewriter &rewriter)
const override {
756 rewriter.replaceOpWithNewOp<om::ConstantOp>(
757 op, rewriter.getBoolAttr(adaptor.getValue()));
764 using OpConversionPattern::OpConversionPattern;
768 ConversionPatternRewriter &rewriter)
const override {
769 rewriter.replaceOpWithNewOp<om::ConstantOp>(op, adaptor.getValue());
776 using OpConversionPattern::OpConversionPattern;
780 ConversionPatternRewriter &rewriter)
const override {
782 rewriter.replaceOpWithNewOp<om::ConstantOp>(
790 using OpConversionPattern::OpConversionPattern;
794 ConversionPatternRewriter &rewriter)
const override {
795 auto listType = getTypeConverter()->convertType<om::ListType>(op.getType());
798 rewriter.replaceOpWithNewOp<om::ListCreateOp>(op, listType,
799 adaptor.getElements());
807 const PathInfoTable &pathInfoTable,
808 PatternBenefit benefit = 1)
810 pathInfoTable(pathInfoTable) {}
814 ConversionPatternRewriter &rewriter)
const override {
815 auto *context = op->getContext();
817 auto pathInfo = pathInfoTable.lookup(op.getTarget());
820 auto basePath = op->getBlock()->getArgument(0);
825 if (op.getTargetKind() == firrtl::TargetKind::DontTouch)
826 return emitError(op.getLoc(),
"DontTouch target was deleted");
827 if (op.getTargetKind() == firrtl::TargetKind::Instance)
828 return emitError(op.getLoc(),
"Instance target was deleted");
829 rewriter.replaceOpWithNewOp<om::EmptyPathOp>(op);
833 auto symbol = pathInfo.symRef;
837 om::TargetKind targetKind;
838 switch (op.getTargetKind()) {
839 case firrtl::TargetKind::DontTouch:
840 targetKind = om::TargetKind::DontTouch;
842 case firrtl::TargetKind::Reference:
843 targetKind = om::TargetKind::Reference;
845 case firrtl::TargetKind::Instance:
846 if (!isa<InstanceOp, FModuleLike>(pathInfo.op))
847 return emitError(op.getLoc(),
"invalid target for instance path")
848 .attachNote(pathInfo.op->getLoc())
849 <<
"target not instance or module";
850 targetKind = om::TargetKind::Instance;
852 case firrtl::TargetKind::MemberInstance:
853 case firrtl::TargetKind::MemberReference:
854 if (isa<InstanceOp, FModuleLike>(pathInfo.op))
855 targetKind = om::TargetKind::MemberInstance;
857 targetKind = om::TargetKind::MemberReference;
861 rewriter.replaceOpWithNewOp<om::PathCreateOp>(
871 using OpConversionPattern::OpConversionPattern;
875 ConversionPatternRewriter &rewriter)
const override {
876 auto wireValue = dyn_cast<FIRRTLPropertyValue>(wireOp.getResult());
885 auto regionKindInterface = wireOp->getParentOfType<RegionKindInterface>();
886 if (!regionKindInterface)
888 if (regionKindInterface.getRegionKind(0) != RegionKind::Graph)
895 rewriter.replaceOp(wireOp, propAssign.getSrc());
898 rewriter.eraseOp(propAssign);
905 using OpConversionPattern::OpConversionPattern;
909 ConversionPatternRewriter &rewriter)
const override {
910 rewriter.replaceOpWithNewOp<AnyCastOp>(op, adaptor.getInput());
917 using OpConversionPattern::OpConversionPattern;
920 const TypeConverter &typeConverter, MLIRContext *context,
921 const DenseMap<StringAttr, firrtl::ClassType> &classTypeTable)
923 classTypeTable(classTypeTable) {}
927 ConversionPatternRewriter &rewriter)
const override {
928 auto omClassType = dyn_cast<om::ClassType>(adaptor.getInput().getType());
934 auto firrtlClassType =
935 classTypeTable.lookup(omClassType.getClassName().getAttr());
936 if (!firrtlClassType)
939 const auto &element = firrtlClassType.getElement(op.getIndex());
941 if (element.direction == Direction::In)
945 auto path = rewriter.getArrayAttr({field});
946 auto type = typeConverter->convertType(element.type);
947 rewriter.replaceOpWithNewOp<om::ObjectFieldOp>(op, type, adaptor.getInput(),
956 using OpConversionPattern::OpConversionPattern;
960 ConversionPatternRewriter &rewriter)
const override {
961 rewriter.replaceOpWithNewOp<ClassFieldOp>(op, adaptor.getSymNameAttr(),
969 using OpConversionPattern::OpConversionPattern;
973 ConversionPatternRewriter &rewriter)
const override {
974 auto type = typeConverter->convertType(adaptor.getType());
977 rewriter.replaceOpWithNewOp<ClassExternFieldOp>(
978 op, adaptor.getSymNameAttr(), type);
984 using OpConversionPattern::OpConversionPattern;
988 ConversionPatternRewriter &rewriter)
const override {
991 rewriter.replaceOpWithNewOp<om::ObjectOp>(objectOp, objectOp.getType(),
992 adaptor.getClassNameAttr(),
993 adaptor.getActualParams());
999 using OpConversionPattern::OpConversionPattern;
1003 ConversionPatternRewriter &rewriter)
const override {
1004 Block *body = classOp.getBodyBlock();
1005 TypeConverter::SignatureConversion result(body->getNumArguments());
1008 if (failed(typeConverter->convertSignatureArgs(body->getArgumentTypes(),
1013 if (failed(rewriter.convertRegionTypes(body->getParent(), *typeConverter,
1017 rewriter.updateRootInPlace(classOp, []() {});
1025 using OpConversionPattern::OpConversionPattern;
1029 ConversionPatternRewriter &rewriter)
const override {
1030 Block *body = classOp.getBodyBlock();
1031 TypeConverter::SignatureConversion result(body->getNumArguments());
1034 if (failed(typeConverter->convertSignatureArgs(body->getArgumentTypes(),
1039 if (failed(rewriter.convertRegionTypes(body->getParent(), *typeConverter,
1043 rewriter.updateRootInPlace(classOp, []() {});
1050 using OpConversionPattern::OpConversionPattern;
1054 ConversionPatternRewriter &rewriter)
const override {
1057 auto type = typeConverter->convertType(op.getType());
1061 rewriter.replaceOpWithNewOp<ObjectFieldOp>(op, type, adaptor.getObject(),
1062 adaptor.getFieldPathAttr());
1073 target.addDynamicallyLegalDialect<FIRRTLDialect>(
1074 [](Operation *op) {
return !op->getParentOfType<om::ClassLike>(); });
1077 target.addDynamicallyLegalDialect<OMDialect>([](Operation *op) {
1078 auto containsFIRRTLType = [](Type type) {
1080 .walk([](Type type) {
1081 return failure(isa<FIRRTLDialect>(type.getDialect()));
1085 auto noFIRRTLOperands =
1086 llvm::none_of(op->getOperandTypes(), [&containsFIRRTLType](Type type) {
1087 return containsFIRRTLType(type);
1089 auto noFIRRTLResults =
1090 llvm::none_of(op->getResultTypes(), [&containsFIRRTLType](Type type) {
1091 return containsFIRRTLType(type);
1093 return noFIRRTLOperands && noFIRRTLResults;
1098 target.addDynamicallyLegalOp<ClassExternFieldOp>(
1099 [](ClassExternFieldOp op) {
return !isa<FIRRTLType>(op.getType()); });
1102 target.addDynamicallyLegalOp<om::ClassOp, om::ClassExternOp>(
1103 [](Operation *op) -> std::optional<bool> {
1104 auto classLike = dyn_cast<om::ClassLike>(op);
1106 return std::nullopt;
1108 return llvm::none_of(
1109 classLike.getBodyBlock()->getArgumentTypes(),
1110 [](Type type) { return isa<FIRRTLDialect>(type.getDialect()); });
1116 converter.addConversion(
1118 converter.addConversion([](FIntegerType type) {
1126 converter.addConversion([](om::StringType type) {
return type; });
1127 converter.addConversion([](firrtl::StringType type) {
1132 converter.addConversion([](om::PathType type) {
return type; });
1133 converter.addConversion([](om::BasePathType type) {
return type; });
1134 converter.addConversion([](om::FrozenPathType type) {
return type; });
1135 converter.addConversion([](om::FrozenBasePathType type) {
return type; });
1136 converter.addConversion([](firrtl::PathType type) {
1141 converter.addConversion([](om::ClassType type) {
return type; });
1142 converter.addConversion([](firrtl::ClassType type) {
1147 converter.addConversion([](om::AnyType type) {
return type; });
1148 converter.addConversion([](firrtl::AnyRefType type) {
1153 auto convertListType = [&converter](
auto type) -> std::optional<mlir::Type> {
1154 auto elementType = converter.convertType(type.getElementType());
1160 converter.addConversion(
1161 [convertListType](om::ListType type) -> std::optional<mlir::Type> {
1163 return convertListType(type);
1166 converter.addConversion(
1167 [convertListType](firrtl::ListType type) -> std::optional<mlir::Type> {
1169 return convertListType(type);
1173 converter.addConversion(
1177 converter.addConversion(
1178 [](DoubleType type) {
return FloatType::getF64(type.getContext()); });
1181 converter.addTargetMaterialization(
1182 [](OpBuilder &
builder, Type type, ValueRange values, Location loc) {
1183 assert(values.size() == 1);
1188 converter.addSourceMaterialization(
1189 [](OpBuilder &
builder, Type type, ValueRange values, Location loc) {
1190 assert(values.size() == 1);
1196 RewritePatternSet &
patterns, TypeConverter &converter,
1197 const PathInfoTable &pathInfoTable,
1198 const DenseMap<StringAttr, firrtl::ClassType> &classTypeTable) {
1220 LogicalResult LowerClassesPass::dialectConversion(
1221 Operation *op,
const PathInfoTable &pathInfoTable,
1222 const DenseMap<StringAttr, firrtl::ClassType> &classTypeTable) {
1223 ConversionTarget target(getContext());
1226 TypeConverter typeConverter;
1229 RewritePatternSet
patterns(&getContext());
1233 return applyPartialConversion(op, target, std::move(
patterns));
assert(baseType &&"element must be base type")
MlirType uint64_t numElements
static void populateConversionTarget(ConversionTarget &target)
static LogicalResult updateModuleInstanceModule(InstanceOp firrtlInstance, OpBuilder &builder, SmallVectorImpl< Operation * > &opsToErase, InstanceGraph &instanceGraph)
static void populateTypeConverter(TypeConverter &converter)
static LogicalResult updateObjectInstance(firrtl::ObjectOp firrtlObject, OpBuilder &builder, SmallVectorImpl< Operation * > &opsToErase)
static LogicalResult updateModuleInstanceClass(InstanceOp firrtlInstance, OpBuilder &builder, SmallVectorImpl< Operation * > &opsToErase, SymbolTable &symbolTable)
static void populateRewritePatterns(RewritePatternSet &patterns, TypeConverter &converter, const PathInfoTable &pathInfoTable, const DenseMap< StringAttr, firrtl::ClassType > &classTypeTable)
This class provides a read-only projection of an annotation.
unsigned getFieldID() const
Get the field id this attribute targets.
AttrClass getMember(StringAttr name) const
Return a member of the annotation.
bool isClass(Args... names) const
Return true if this annotation matches any of the specified class names.
This graph tracks modules and where they are instantiated.
virtual void replaceInstance(InstanceOpInterface inst, InstanceOpInterface newInst)
Replaces an instance of a module with another instance.
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
hw::InnerRefAttr getInnerRefTo(const hw::InnerSymTarget &target, GetNamespaceCallback getNamespace)
Obtain an inner reference to the target (operation or port), adding an inner symbol as necessary.
PropAssignOp getPropertyAssignment(FIRRTLPropertyValue value)
Return the single assignment to a Property value.
std::unique_ptr< mlir::Pass > createLowerClassesPass()
This file defines an intermediate representation for circuits acting as an abstraction for constraint...
LogicalResult matchAndRewrite(ObjectAnyRefCastOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(BoolConstantOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(ClassExternFieldOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(om::ClassExternOp classOp, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(ClassFieldOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(om::ClassOp classOp, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(DoubleConstantOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(FIntegerConstantOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(firrtl::ListCreateOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(ObjectFieldOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(om::ObjectOp objectOp, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
ObjectSubfieldOpConversion(const TypeConverter &typeConverter, MLIRContext *context, const DenseMap< StringAttr, firrtl::ClassType > &classTypeTable)
const DenseMap< StringAttr, firrtl::ClassType > & classTypeTable
LogicalResult matchAndRewrite(firrtl::ObjectSubfieldOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
PathOpConversion(TypeConverter &typeConverter, MLIRContext *context, const PathInfoTable &pathInfoTable, PatternBenefit benefit=1)
const PathInfoTable & pathInfoTable
LogicalResult matchAndRewrite(firrtl::PathOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(StringConstantOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(WireOp wireOp, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
An annotation target is used to keep track of something that is targeted by an Annotation.
A cache of existing HierPathOps, mostly used to facilitate HierPathOp reuse.
This represents an annotation targeting a specific operation.
This represents an annotation targeting a specific port of a module, memory, or instance.
This holds the name and type that describes the module's ports.