17 #include "mlir/IR/DialectImplementation.h"
18 #include "llvm/ADT/StringExtras.h"
19 #include "llvm/ADT/StringSwitch.h"
20 #include "llvm/ADT/TypeSwitch.h"
22 using namespace circt;
23 using namespace firrtl;
25 using mlir::OptionalParseResult;
26 using mlir::TypeStorageAllocator;
33 #define GET_TYPEDEF_CLASSES
34 #include "circt/Dialect/FIRRTL/FIRRTLTypes.cpp.inc"
50 auto printWidthQualifier = [&](std::optional<int32_t>
width) {
52 os << '<' << *width << '>
';
54 bool anyFailed = false;
55 TypeSwitch<Type>(type)
56 .Case<ClockType>([&](auto) { os << "clock"; })
57 .Case<ResetType>([&](auto) { os << "reset"; })
58 .Case<AsyncResetType>([&](auto) { os << "asyncreset"; })
59 .Case<SIntType>([&](auto sIntType) {
61 printWidthQualifier(sIntType.getWidth());
63 .Case<UIntType>([&](auto uIntType) {
65 printWidthQualifier(uIntType.getWidth());
67 .Case<AnalogType>([&](auto analogType) {
69 printWidthQualifier(analogType.getWidth());
71 .Case<BundleType, OpenBundleType>([&](auto bundleType) {
72 if (firrtl::type_isa<OpenBundleType>(bundleType))
75 llvm::interleaveComma(bundleType, os, [&](auto element) {
76 StringRef fieldName = element.name.getValue();
77 bool isLiteralIdentifier =
78 !fieldName.empty() && llvm::isDigit(fieldName.front());
79 if (isLiteralIdentifier)
81 os << element.name.getValue();
82 if (isLiteralIdentifier)
87 printNestedType(element.type, os);
91 .Case<FEnumType>([&](auto fenumType) {
93 llvm::interleaveComma(fenumType, os,
94 [&](FEnumType::EnumElement element) {
95 os << element.name.getValue();
97 printNestedType(element.type, os);
101 .Case<FVectorType, OpenVectorType>([&](auto vectorType) {
102 if (firrtl::type_isa<OpenVectorType>(vectorType))
105 printNestedType(vectorType.getElementType(), os);
106 os << ", " << vectorType.getNumElements() << '>
';
108 .Case<RefType>([&](auto refType) {
109 if (refType.getForceable())
112 printNestedType(refType.getType(), os);
115 .Case<StringType>([&](auto stringType) { os << "string"; })
116 .Case<FIntegerType>([&](auto integerType) { os << "integer"; })
117 .Case<BoolType>([&](auto boolType) { os << "bool"; })
118 .Case<DoubleType>([&](auto doubleType) { os << "double"; })
119 .Case<ListType>([&](auto listType) {
121 printNestedType(listType.getElementType(), os);
124 .Case<PathType>([&](auto pathType) { os << "path"; })
125 .Case<BaseTypeAliasType>([&](BaseTypeAliasType alias) {
126 os << "alias<" << alias.getName().getValue() << ", ";
127 printNestedType(alias.getInnerType(), os);
130 .Case<ClassType>([&](ClassType type) {
132 type.printInterface(os);
135 .Case<AnyRefType>([&](AnyRefType type) { os << "anyref"; })
136 .Default([&](auto) { anyFailed = true; });
137 return failure(anyFailed);
139 // NOLINTEND(misc-no-recursion)
142 void circt::firrtl::printNestedType(Type type, AsmPrinter &os) {
143 // Try the custom type printer.
144 if (succeeded(customTypePrinter(type, os)))
147 // None of the above recognized the type, so we bail.
148 assert(false && "type to print unknown to FIRRTL dialect");
151 //===----------------------------------------------------------------------===//
153 //===----------------------------------------------------------------------===//
180 static OptionalParseResult customTypeParser(AsmParser &parser, StringRef name,
182 bool isConst = false;
183 const char constPrefix[] = "const.";
184 if (name.starts_with(constPrefix)) {
186 name = name.drop_front(std::size(constPrefix) - 1);
189 auto *context = parser.getContext();
190 if (name.equals("clock"))
191 return result = ClockType::get(context, isConst), success();
192 if (name.equals("reset"))
193 return result = ResetType::get(context, isConst), success();
194 if (name.equals("asyncreset"))
195 return result = AsyncResetType::get(context, isConst), success();
197 if (name.equals("sint") || name.equals("uint") || name.equals("analog")) {
198 // Parse the width specifier if it exists.
200 if (!parser.parseOptionalLess()) {
201 if (parser.parseInteger(width) || parser.parseGreater())
205 return parser.emitError(parser.getNameLoc(), "unknown width"),
209 if (name.equals("sint"))
210 result = SIntType::get(context, width, isConst);
211 else if (name.equals("uint"))
212 result = UIntType::get(context, width, isConst);
214 assert(name.equals("analog"));
215 result = AnalogType::get(context, width, isConst);
220 if (name.equals("bundle")) {
221 SmallVector<BundleType::BundleElement, 4> elements;
223 auto parseBundleElement = [&]() -> ParseResult {
228 if (failed(parser.parseKeywordOrString(&nameStr)))
232 bool isFlip = succeeded(parser.parseOptionalKeyword("flip"));
233 if (parser.parseColon() || parseNestedBaseType(type, parser))
236 elements.push_back({StringAttr::get(context, name), isFlip, type});
240 if (parser.parseCommaSeparatedList(mlir::AsmParser::Delimiter::LessGreater,
244 return result = BundleType::get(context, elements, isConst), success();
246 if (name.equals("openbundle")) {
247 SmallVector<OpenBundleType::BundleElement, 4> elements;
249 auto parseBundleElement = [&]() -> ParseResult {
254 if (failed(parser.parseKeywordOrString(&nameStr)))
258 bool isFlip = succeeded(parser.parseOptionalKeyword("flip"));
259 if (parser.parseColon() || parseNestedType(type, parser))
262 elements.push_back({StringAttr::get(context, name), isFlip, type});
266 if (parser.parseCommaSeparatedList(mlir::AsmParser::Delimiter::LessGreater,
270 result = parser.getChecked<OpenBundleType>(context, elements, isConst);
271 return failure(!result);
274 if (name.equals("enum")) {
275 SmallVector<FEnumType::EnumElement, 4> elements;
277 auto parseEnumElement = [&]() -> ParseResult {
282 if (failed(parser.parseKeywordOrString(&nameStr)))
286 if (parser.parseColon() || parseNestedBaseType(type, parser))
289 elements.push_back({StringAttr::get(context, name), type});
293 if (parser.parseCommaSeparatedList(mlir::AsmParser::Delimiter::LessGreater,
296 if (failed(FEnumType::verify(
297 [&]() { return parser.emitError(parser.getNameLoc()); }, elements,
301 return result = FEnumType::get(context, elements, isConst), success();
304 if (name.equals("vector")) {
305 FIRRTLBaseType elementType;
308 if (parser.parseLess() || parseNestedBaseType(elementType, parser) ||
309 parser.parseComma() || parser.parseInteger(width) ||
310 parser.parseGreater())
313 return result = FVectorType::get(elementType, width, isConst), success();
315 if (name.equals("openvector")) {
316 FIRRTLType elementType;
319 if (parser.parseLess() || parseNestedType(elementType, parser) ||
320 parser.parseComma() || parser.parseInteger(width) ||
321 parser.parseGreater())
325 parser.getChecked<OpenVectorType>(context, elementType, width, isConst);
326 return failure(!result);
329 // For now, support both firrtl.ref and firrtl.probe.
330 if (name.equals("ref") || name.equals("probe")) {
335 parser.parseGreater())
338 if (failed(RefType::verify(
339 [&]() {
return parser.emitError(parser.getNameLoc()); }, type,
345 if (name.equals(
"rwprobe")) {
348 parser.parseGreater())
351 if (failed(RefType::verify(
352 [&]() {
return parser.emitError(parser.getNameLoc()); }, type,
358 if (name.equals(
"class")) {
360 return parser.emitError(parser.getNameLoc(),
"classes cannot be const");
362 if (parser.parseLess() || ClassType::parseInterface(parser, classType) ||
363 parser.parseGreater())
368 if (name.equals(
"anyref")) {
370 return parser.emitError(parser.getNameLoc(),
"any refs cannot be const");
375 if (name.equals(
"string")) {
377 parser.emitError(parser.getNameLoc(),
"strings cannot be const");
383 if (name.equals(
"integer")) {
385 parser.emitError(parser.getNameLoc(),
"bigints cannot be const");
391 if (name.equals(
"bool")) {
393 parser.emitError(parser.getNameLoc(),
"bools cannot be const");
399 if (name.equals(
"double")) {
401 parser.emitError(parser.getNameLoc(),
"doubles cannot be const");
407 if (name.equals(
"list")) {
409 parser.emitError(parser.getNameLoc(),
"lists cannot be const");
414 parser.parseGreater())
416 result = parser.getChecked<ListType>(context,
elementType);
421 if (name.equals(
"path")) {
423 parser.emitError(parser.getNameLoc(),
"path cannot be const");
429 if (name.equals(
"alias")) {
432 if (parser.parseLess() || parser.parseKeyword(&name) ||
434 parser.parseGreater())
450 static ParseResult
parseType(Type &result, StringRef name, AsmParser &parser) {
453 if (parseResult.has_value())
454 return parseResult.value();
457 parser.emitError(parser.getNameLoc(),
"unknown FIRRTL dialect type: \"")
469 if (failed(
parseType(type, name, parser)))
471 result = type_dyn_cast<FIRRTLType>(type);
474 parser.emitError(parser.getNameLoc(),
"unknown FIRRTL type: \"")
484 if (
auto base = type_dyn_cast<FIRRTLBaseType>(type)) {
488 parser.emitError(parser.getNameLoc(),
"expected base type, found ") << type;
497 if (
auto prop = type_dyn_cast<PropertyType>(type)) {
501 parser.emitError(parser.getNameLoc(),
"expected property type, found ")
514 if (parser.parseKeyword(&name))
524 if (parser.parseKeyword(&name))
534 if (parser.parseKeyword(&name))
545 void FIRRTLDialect::printType(Type type, DialectAsmPrinter &os)
const {
553 if (parser.parseKeyword(&name) || ::
parseType(result, name, parser))
597 return TypeSwitch<FIRRTLType, bool>(*
this)
598 .Case<ClockType, ResetType, AsyncResetType, SIntType, UIntType,
599 AnalogType>([](Type) {
return true; })
600 .Case<BundleType, FVectorType, FEnumType, OpenBundleType, OpenVectorType>(
601 [](Type) {
return false; })
602 .Case<BaseTypeAliasType>([](BaseTypeAliasType alias) {
603 return alias.getAnonymousType().isGround();
606 .Case<PropertyType, RefType>([](Type) {
return false; })
608 llvm_unreachable(
"unknown FIRRTL type");
614 return TypeSwitch<FIRRTLType, bool>(*
this)
616 [](
auto type) {
return type.
isConst(); })
623 return TypeSwitch<FIRRTLType, RecursiveTypeProperties>(*
this)
624 .Case<ClockType, ResetType, AsyncResetType>([](
FIRRTLBaseType type) {
631 firrtl::type_isa<ResetType>(type)};
633 .Case<SIntType, UIntType>([](
auto type) {
635 true,
false,
false, type.
isConst(),
false, !type.hasWidth(),
false};
637 .Case<AnalogType>([](
auto type) {
639 true,
false,
true, type.
isConst(),
false, !type.hasWidth(),
false};
641 .Case<BundleType, FVectorType, FEnumType, OpenBundleType, OpenVectorType,
642 RefType, BaseTypeAliasType>(
643 [](
auto type) {
return type.getRecursiveTypeProperties(); })
644 .Case<PropertyType>([](
auto type) {
646 false,
false,
false};
649 llvm_unreachable(
"unknown FIRRTL type");
656 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
657 .Case<ClockType, ResetType, AsyncResetType, SIntType, UIntType,
658 AnalogType>([&](Type) {
return *
this; })
659 .Case<BundleType, FVectorType, FEnumType, BaseTypeAliasType>(
662 llvm_unreachable(
"unknown FIRRTL type");
669 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
670 .Case<ClockType, ResetType, AsyncResetType, SIntType, UIntType,
671 AnalogType, FEnumType>([&](Type) {
return *
this; })
672 .Case<BundleType, FVectorType, FEnumType, BaseTypeAliasType>(
675 llvm_unreachable(
"unknown FIRRTL type");
682 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
683 .Case<ClockType, ResetType, AsyncResetType, AnalogType, SIntType,
684 UIntType, BundleType, FVectorType, FEnumType, BaseTypeAliasType>(
687 llvm_unreachable(
"unknown FIRRTL type");
694 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
695 .Case<ClockType, ResetType, AsyncResetType, AnalogType, SIntType,
696 UIntType>([&](
auto type) {
return type.
getConstType(
false); })
697 .Case<BundleType, FVectorType, FEnumType, BaseTypeAliasType>(
700 llvm_unreachable(
"unknown FIRRTL type");
708 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
709 .Case<ClockType, ResetType, AsyncResetType, SIntType, UIntType,
710 AnalogType>([&](Type) {
713 .Case<BundleType>([&](BundleType bundleType) {
714 SmallVector<BundleType::BundleElement, 4> newElements;
715 newElements.reserve(bundleType.getElements().size());
716 for (
auto elt : bundleType)
717 newElements.push_back(
718 {elt.name,
false , elt.type.getMaskType()});
720 bundleType.isConst());
722 .Case<FVectorType>([](FVectorType vectorType) {
724 vectorType.getNumElements(),
725 vectorType.isConst());
727 .Case<BaseTypeAliasType>([](BaseTypeAliasType base) {
728 return base.getModifiedType(base.getInnerType().getMaskType());
731 llvm_unreachable(
"unknown FIRRTL type");
739 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
740 .Case<ClockType, ResetType, AsyncResetType>([](
auto a) {
return a; })
741 .Case<UIntType, SIntType, AnalogType>(
742 [&](
auto a) {
return a.get(this->getContext(), -1, a.isConst()); })
743 .Case<BundleType>([&](
auto a) {
744 SmallVector<BundleType::BundleElement, 4> newElements;
745 newElements.reserve(a.getElements().size());
747 newElements.push_back(
748 {elt.name, elt.isFlip, elt.type.getWidthlessType()});
751 .Case<FVectorType>([](
auto a) {
753 a.getNumElements(), a.isConst());
755 .Case<FEnumType>([&](FEnumType a) {
756 SmallVector<FEnumType::EnumElement, 4> newElements;
757 newElements.reserve(a.getNumElements());
759 newElements.push_back({elt.name, elt.type.getWidthlessType()});
760 return FEnumType::get(this->getContext(), newElements, a.isConst());
762 .Case<BaseTypeAliasType>([](BaseTypeAliasType type) {
763 return type.getModifiedType(type.getInnerType().getWidthlessType());
766 llvm_unreachable(
"unknown FIRRTL type");
776 return TypeSwitch<FIRRTLBaseType, int32_t>(*
this)
777 .Case<ClockType, ResetType, AsyncResetType>([](Type) {
return 1; })
778 .Case<SIntType, UIntType>(
781 [](AnalogType analogType) {
return analogType.getWidthOrSentinel(); })
782 .Case<BundleType, FVectorType, FEnumType>([](Type) {
return -2; })
783 .Case<BaseTypeAliasType>([](BaseTypeAliasType type) {
785 return type.getAnonymousType().getBitWidthOrSentinel();
788 llvm_unreachable(
"unknown FIRRTL type");
797 return TypeSwitch<FIRRTLType, bool>(*
this)
798 .Case<ResetType, AsyncResetType>([](Type) {
return true; })
800 [](UIntType a) {
return !a.hasWidth() || a.getWidth() == 1; })
801 .Case<BaseTypeAliasType>(
802 [](
auto type) {
return type.getInnerType().
isResetType(); })
803 .Default([](Type) {
return false; });
807 return TypeSwitch<Type, bool>(type)
809 [](
auto base) {
return base.isConst(); })
814 return TypeSwitch<Type, bool>(type)
816 [](
auto base) {
return base.containsConst(); })
826 BundleType::BundleElement srcElement,
827 bool destOuterTypeIsConst,
828 bool srcOuterTypeIsConst,
829 bool requiresSameWidth) {
830 if (destElement.name != srcElement.name)
832 if (destElement.isFlip != srcElement.isFlip)
835 if (destElement.isFlip) {
836 std::swap(destElement, srcElement);
837 std::swap(destOuterTypeIsConst, srcOuterTypeIsConst);
841 destOuterTypeIsConst, srcOuterTypeIsConst,
850 bool destOuterTypeIsConst,
851 bool srcOuterTypeIsConst,
852 bool requireSameWidths) {
853 auto destType = type_dyn_cast<FIRRTLBaseType>(destFType);
854 auto srcType = type_dyn_cast<FIRRTLBaseType>(srcFType);
857 if (!destType || !srcType)
858 return destFType == srcFType;
860 bool srcIsConst = srcOuterTypeIsConst || srcFType.
isConst();
861 bool destIsConst = destOuterTypeIsConst || destFType.
isConst();
864 auto destVectorType = type_dyn_cast<FVectorType>(destType);
865 auto srcVectorType = type_dyn_cast<FVectorType>(srcType);
866 if (destVectorType && srcVectorType)
867 return destVectorType.getNumElements() == srcVectorType.getNumElements() &&
869 srcVectorType.getElementType(), destIsConst,
870 srcIsConst, requireSameWidths);
874 auto destBundleType = type_dyn_cast<BundleType>(destType);
875 auto srcBundleType = type_dyn_cast<BundleType>(srcType);
876 if (destBundleType && srcBundleType) {
877 auto destElements = destBundleType.getElements();
878 auto srcElements = srcBundleType.getElements();
879 size_t numDestElements = destElements.size();
880 if (numDestElements != srcElements.size())
883 for (
size_t i = 0; i < numDestElements; ++i) {
884 auto destElement = destElements[i];
885 auto srcElement = srcElements[i];
887 srcIsConst, requireSameWidths))
895 auto dstEnumType = type_dyn_cast<FEnumType>(destType);
896 auto srcEnumType = type_dyn_cast<FEnumType>(srcType);
898 if (dstEnumType && srcEnumType) {
899 if (dstEnumType.getNumElements() != srcEnumType.getNumElements())
902 for (
const auto &[dst, src] : llvm::zip(dstEnumType, srcEnumType)) {
904 if (dst.name != src.name)
916 if (destIsConst && !srcIsConst)
920 if (firrtl::type_isa<ResetType>(destType))
921 return srcType.isResetType();
924 if (firrtl::type_isa<ResetType>(srcType))
925 return destType.isResetType();
929 if (!requireSameWidths || destType.getBitWidthOrSentinel() == -1)
930 srcType = srcType.getWidthlessType();
931 if (!requireSameWidths || srcType.getBitWidthOrSentinel() == -1)
932 destType = destType.getWidthlessType();
935 return destType.getConstType(
false) == srcType.getConstType(
false);
940 bool destFlip,
bool srcFlip,
941 bool destOuterTypeIsConst,
942 bool srcOuterTypeIsConst) {
943 auto destType = type_dyn_cast<FIRRTLBaseType>(destFType);
944 auto srcType = type_dyn_cast<FIRRTLBaseType>(srcFType);
947 if (!destType || !srcType)
948 return destFType == srcFType;
950 bool srcIsConst = srcOuterTypeIsConst || srcFType.
isConst();
951 bool destIsConst = destOuterTypeIsConst || destFType.
isConst();
955 auto destVectorType = type_dyn_cast<FVectorType>(destType);
956 auto srcVectorType = type_dyn_cast<FVectorType>(srcType);
957 if (destVectorType && srcVectorType)
959 srcVectorType.getElementType(), destFlip,
960 srcFlip, destIsConst, srcIsConst);
965 auto destBundleType = type_dyn_cast<BundleType>(destType);
966 auto srcBundleType = type_dyn_cast<BundleType>(srcType);
967 if (destBundleType && srcBundleType)
968 return llvm::all_of(destBundleType, [&](
auto destElt) ->
bool {
969 auto destField = destElt.name.getValue();
970 auto srcElt = srcBundleType.getElement(destField);
976 destElt.type, srcElt->type, destFlip ^ destElt.isFlip,
977 srcFlip ^ srcElt->isFlip, destOuterTypeIsConst, srcOuterTypeIsConst);
981 if (destFlip != srcFlip)
983 if (destFlip && srcIsConst && !destIsConst)
985 if (srcFlip && destIsConst && !srcIsConst)
989 if (type_isa<ResetType>(destType))
990 return srcType.isResetType();
993 if (type_isa<ResetType>(srcType))
994 return destType.isResetType();
998 auto widthlessDestType = destType.getWidthlessType();
999 auto widthlessSrcType = srcType.getWidthlessType();
1000 return widthlessDestType.getConstType(
false) ==
1001 widthlessSrcType.getConstType(
false);
1006 bool srcOuterTypeIsConst) {
1008 if (destFType == srcFType)
1011 auto destType = type_dyn_cast<FIRRTLBaseType>(destFType);
1012 auto srcType = type_dyn_cast<FIRRTLBaseType>(srcFType);
1015 if (!destType || !srcType)
1019 if (!destType.isPassive() || !srcType.isPassive())
1022 bool srcIsConst = srcType.isConst() || srcOuterTypeIsConst;
1025 if (destType.isConst() && !srcIsConst)
1030 auto destVectorType = type_dyn_cast<FVectorType>(destType);
1031 auto srcVectorType = type_dyn_cast<FVectorType>(srcType);
1032 if (destVectorType && srcVectorType)
1033 return destVectorType.getNumElements() == srcVectorType.getNumElements() &&
1035 srcVectorType.getElementType(), srcIsConst);
1036 if (destVectorType != srcVectorType)
1041 auto destBundleType = type_dyn_cast<BundleType>(destType);
1042 auto srcBundleType = type_dyn_cast<BundleType>(srcType);
1043 if (destBundleType && srcBundleType) {
1044 auto destElements = destBundleType.getElements();
1045 auto srcElements = srcBundleType.getElements();
1046 size_t numDestElements = destElements.size();
1047 if (numDestElements != srcElements.size())
1050 return llvm::all_of_zip(
1051 destElements, srcElements,
1052 [&](
const auto &destElement,
const auto &srcElement) {
1053 return destElement.name == srcElement.name &&
1058 if (destBundleType != srcBundleType)
1063 return destType == srcType.getConstType(destType.isConst());
1067 auto dstRefType = type_dyn_cast<RefType>(dstType);
1068 auto srcRefType = type_dyn_cast<RefType>(srcType);
1069 if (!dstRefType || !srcRefType)
1071 if (dstRefType == srcRefType)
1073 if (dstRefType.getForceable() && !srcRefType.getForceable())
1085 bool srcOuterTypeIsConst) ->
bool {
1091 assert(dest.isPassive() && src.isPassive());
1093 bool srcIsConst = src.isConst() || srcOuterTypeIsConst;
1096 if (dest.isConst() && !srcIsConst)
1102 if (
auto destVectorType = type_dyn_cast<FVectorType>(dest)) {
1103 auto srcVectorType = type_dyn_cast<FVectorType>(src);
1104 return srcVectorType &&
1105 destVectorType.getNumElements() ==
1106 srcVectorType.getNumElements() &&
1107 f(f, destVectorType.getElementType(),
1108 srcVectorType.getElementType(), srcIsConst);
1111 if (
auto destBundleType = type_dyn_cast<BundleType>(dest)) {
1112 auto srcBundleType = type_dyn_cast<BundleType>(src);
1116 auto destElements = destBundleType.getElements();
1117 auto srcElements = srcBundleType.getElements();
1119 return destElements.size() == srcElements.size() &&
1121 destElements, srcElements,
1122 [&](
const auto &destElement,
const auto &srcElement) {
1123 return destElement.name == srcElement.name &&
1124 f(f, destElement.type, srcElement.type, srcIsConst);
1128 if (
auto destEnumType = type_dyn_cast<FEnumType>(dest)) {
1129 auto srcEnumType = type_dyn_cast<FEnumType>(src);
1132 auto destElements = destEnumType.getElements();
1133 auto srcElements = srcEnumType.getElements();
1135 return destElements.size() == srcElements.size() &&
1137 destElements, srcElements,
1138 [&](
const auto &destElement,
const auto &srcElement) {
1139 return destElement.name == srcElement.name &&
1140 f(f, destElement.type, srcElement.type, srcIsConst);
1145 if (type_isa<ResetType>(dest))
1146 return src.isResetType();
1150 src = src.getConstType(dest.isConst());
1153 if (dest.getBitWidthOrSentinel() == -1)
1154 src = src.getWidthlessType();
1159 return recurse(recurse, dstRefType.getType(), srcRefType.getType(),
false);
1166 return TypeSwitch<FIRRTLBaseType, bool>(dstType)
1167 .Case<BundleType>([&](
auto dstBundle) {
1168 auto srcBundle = type_cast<BundleType>(srcType);
1169 for (
size_t i = 0, n = dstBundle.getNumElements(); i < n; ++i) {
1170 auto srcElem = srcBundle.getElement(i);
1171 auto dstElem = dstBundle.getElement(i);
1172 if (dstElem.isFlip) {
1182 .Case<FVectorType>([&](
auto vector) {
1184 type_cast<FVectorType>(srcType).getElementType());
1186 .Default([&](
auto dstGround) {
1189 return destWidth <= -1 || srcWidth <= -1 || destWidth >= srcWidth;
1200 if (
auto destBaseType = type_dyn_cast<FIRRTLBaseType>(lhs))
1201 if (
auto srcBaseType = type_dyn_cast<FIRRTLBaseType>(rhs))
1204 if (
auto destRefType = type_dyn_cast<RefType>(lhs))
1205 if (
auto srcRefType = type_dyn_cast<RefType>(rhs))
1207 srcRefType.getType());
1215 return type_cast<FIRRTLBaseType>(anyBaseFIRRTLType).getPassiveType();
1219 return llvm::TypeSwitch<Type, bool>(type)
1221 return !type.containsReference() &&
1222 (!type.isPassive() || type.containsAnalog());
1234 int32_t widthOrSentinel,
bool isConst) {
1241 if (
auto sintType = type_dyn_cast<SIntType>(*
this))
1242 return sintType.getWidthOrSentinel();
1243 if (
auto uintType = type_dyn_cast<UIntType>(*
this))
1244 return uintType.getWidthOrSentinel();
1272 if (
auto sIntType = type_dyn_cast<SIntType>(*
this))
1281 SIntType
SIntType::get(MLIRContext *context) {
return get(context, -1,
false); }
1288 LogicalResult SIntType::verify(function_ref<InFlightDiagnostic()> emitError,
1289 int32_t widthOrSentinel,
bool isConst) {
1290 if (widthOrSentinel < -1)
1291 return emitError() <<
"invalid width";
1295 int32_t SIntType::getWidthOrSentinel()
const {
return getImpl()->width; }
1297 SIntType SIntType::getConstType(
bool isConst) {
1300 return get(getContext(), getWidthOrSentinel(),
isConst);
1314 LogicalResult UIntType::verify(function_ref<InFlightDiagnostic()> emitError,
1315 int32_t widthOrSentinel,
bool isConst) {
1316 if (widthOrSentinel < -1)
1317 return emitError() <<
"invalid width";
1321 int32_t UIntType::getWidthOrSentinel()
const {
return getImpl()->width; }
1323 UIntType UIntType::getConstType(
bool isConst) {
1326 return get(getContext(), getWidthOrSentinel(),
isConst);
1335 using KeyTy = std::pair<ArrayRef<BundleType::BundleElement>,
char>;
1342 uint64_t fieldID = 0;
1345 auto type = element.type;
1346 auto eltInfo = type.getRecursiveTypeProperties();
1367 return llvm::hash_combine(
1368 llvm::hash_combine_range(key.first.begin(), key.first.end()),
1390 ArrayRef<BundleElement> elements,
bool isConst) {
1394 auto BundleType::getElements() const -> ArrayRef<BundleElement> {
1395 return getImpl()->elements;
1400 return getImpl()->props;
1405 auto *impl = getImpl();
1408 if (impl->passiveType)
1409 return impl->passiveType;
1412 if (impl->props.isPassive) {
1413 impl->passiveType = *
this;
1418 SmallVector<BundleType::BundleElement, 16> newElements;
1419 newElements.reserve(impl->elements.size());
1420 for (
auto &elt : impl->elements) {
1421 newElements.push_back({elt.name,
false, elt.type.getPassiveType()});
1425 impl->passiveType = passiveType;
1429 BundleType BundleType::getConstType(
bool isConst) {
1432 return get(getContext(), getElements(),
isConst);
1435 BundleType BundleType::getAllConstDroppedType() {
1439 SmallVector<BundleElement> constDroppedElements(
1440 llvm::map_range(getElements(), [](BundleElement element) {
1441 element.type = element.type.getAllConstDroppedType();
1444 return get(getContext(), constDroppedElements,
false);
1447 std::optional<unsigned> BundleType::getElementIndex(StringAttr name) {
1448 for (
const auto &it : llvm::enumerate(getElements())) {
1449 auto element = it.value();
1450 if (element.name == name) {
1451 return unsigned(it.index());
1454 return std::nullopt;
1457 std::optional<unsigned> BundleType::getElementIndex(StringRef name) {
1458 for (
const auto &it : llvm::enumerate(getElements())) {
1459 auto element = it.value();
1460 if (element.name.getValue() == name) {
1461 return unsigned(it.index());
1464 return std::nullopt;
1467 StringAttr BundleType::getElementNameAttr(
size_t index) {
1468 assert(index < getNumElements() &&
1469 "index must be less than number of fields in bundle");
1470 return getElements()[index].name;
1473 StringRef BundleType::getElementName(
size_t index) {
1474 return getElementNameAttr(index).getValue();
1477 std::optional<BundleType::BundleElement>
1478 BundleType::getElement(StringAttr name) {
1479 if (
auto maybeIndex = getElementIndex(name))
1480 return getElements()[*maybeIndex];
1481 return std::nullopt;
1484 std::optional<BundleType::BundleElement>
1485 BundleType::getElement(StringRef name) {
1486 if (
auto maybeIndex = getElementIndex(name))
1487 return getElements()[*maybeIndex];
1488 return std::nullopt;
1492 BundleType::BundleElement BundleType::getElement(
size_t index) {
1493 assert(index < getNumElements() &&
1494 "index must be less than number of fields in bundle");
1495 return getElements()[index];
1499 auto element = getElement(name);
1504 auto element = getElement(name);
1509 assert(index < getNumElements() &&
1510 "index must be less than number of fields in bundle");
1511 return getElements()[index].type;
1515 return getImpl()->fieldIDs[index];
1519 assert(!getElements().
empty() &&
"Bundle must have >0 fields");
1520 auto fieldIDs = getImpl()->fieldIDs;
1521 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
1522 return std::distance(fieldIDs.begin(), it);
1525 std::pair<uint64_t, uint64_t>
1529 return {index, fieldID - elementFieldID};
1532 std::pair<Type, uint64_t>
1537 auto subfieldType = getElementType(subfieldIndex);
1538 auto subfieldID = fieldID -
getFieldID(subfieldIndex);
1539 return {subfieldType, subfieldID};
1544 std::pair<uint64_t, bool>
1547 auto rangeEnd = index + 1 >= getNumElements() ?
getMaxFieldID()
1549 return std::make_pair(fieldID - childRoot,
1550 fieldID >= childRoot && fieldID <= rangeEnd);
1555 BundleType::ElementType
1556 BundleType::getElementTypePreservingConst(
size_t index) {
1557 auto type = getElementType(index);
1558 return type.getConstType(type.isConst() ||
isConst());
1563 auto *impl = getImpl();
1566 if (impl->anonymousType)
1567 return impl->anonymousType;
1570 if (!impl->props.containsTypeAlias) {
1571 impl->anonymousType = *
this;
1577 SmallVector<BundleType::BundleElement, 16> newElements;
1578 newElements.reserve(impl->elements.size());
1579 for (
auto &elt : impl->elements)
1580 newElements.push_back({elt.name, elt.isFlip, elt.type.getAnonymousType()});
1583 impl->anonymousType = anonymousType;
1584 return anonymousType;
1592 using KeyTy = std::pair<ArrayRef<OpenBundleType::BundleElement>,
char>;
1600 uint64_t fieldID = 0;
1603 auto type = element.type;
1604 auto eltInfo = type.getRecursiveTypeProperties();
1624 return llvm::hash_combine(
1625 llvm::hash_combine_range(key.first.begin(), key.first.end()),
1637 SmallVector<OpenBundleType::BundleElement, 4>
elements;
1650 ArrayRef<BundleElement> elements,
1655 auto OpenBundleType::getElements() const -> ArrayRef<BundleElement> {
1656 return getImpl()->elements;
1661 return getImpl()->props;
1664 OpenBundleType OpenBundleType::getConstType(
bool isConst) {
1667 return get(getContext(), getElements(),
isConst);
1670 std::optional<unsigned> OpenBundleType::getElementIndex(StringAttr name) {
1671 for (
const auto &it : llvm::enumerate(getElements())) {
1672 auto element = it.value();
1673 if (element.name == name) {
1674 return unsigned(it.index());
1677 return std::nullopt;
1680 std::optional<unsigned> OpenBundleType::getElementIndex(StringRef name) {
1681 for (
const auto &it : llvm::enumerate(getElements())) {
1682 auto element = it.value();
1683 if (element.name.getValue() == name) {
1684 return unsigned(it.index());
1687 return std::nullopt;
1690 StringAttr OpenBundleType::getElementNameAttr(
size_t index) {
1691 assert(index < getNumElements() &&
1692 "index must be less than number of fields in bundle");
1693 return getElements()[index].name;
1696 StringRef OpenBundleType::getElementName(
size_t index) {
1697 return getElementNameAttr(index).getValue();
1700 std::optional<OpenBundleType::BundleElement>
1701 OpenBundleType::getElement(StringAttr name) {
1702 if (
auto maybeIndex = getElementIndex(name))
1703 return getElements()[*maybeIndex];
1704 return std::nullopt;
1707 std::optional<OpenBundleType::BundleElement>
1708 OpenBundleType::getElement(StringRef name) {
1709 if (
auto maybeIndex = getElementIndex(name))
1710 return getElements()[*maybeIndex];
1711 return std::nullopt;
1715 OpenBundleType::BundleElement OpenBundleType::getElement(
size_t index) {
1716 assert(index < getNumElements() &&
1717 "index must be less than number of fields in bundle");
1718 return getElements()[index];
1721 OpenBundleType::ElementType OpenBundleType::getElementType(StringAttr name) {
1722 auto element = getElement(name);
1726 OpenBundleType::ElementType OpenBundleType::getElementType(StringRef name) {
1727 auto element = getElement(name);
1731 OpenBundleType::ElementType OpenBundleType::getElementType(
size_t index)
const {
1732 assert(index < getNumElements() &&
1733 "index must be less than number of fields in bundle");
1734 return getElements()[index].type;
1738 return getImpl()->fieldIDs[index];
1742 assert(!getElements().
empty() &&
"Bundle must have >0 fields");
1743 auto fieldIDs = getImpl()->fieldIDs;
1744 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
1745 return std::distance(fieldIDs.begin(), it);
1748 std::pair<uint64_t, uint64_t>
1752 return {index, fieldID - elementFieldID};
1755 std::pair<Type, uint64_t>
1760 auto subfieldType = getElementType(subfieldIndex);
1761 auto subfieldID = fieldID -
getFieldID(subfieldIndex);
1762 return {subfieldType, subfieldID};
1767 std::pair<uint64_t, bool>
1770 auto rangeEnd = index + 1 >= getNumElements() ?
getMaxFieldID()
1772 return std::make_pair(fieldID - childRoot,
1773 fieldID >= childRoot && fieldID <= rangeEnd);
1778 OpenBundleType::ElementType
1779 OpenBundleType::getElementTypePreservingConst(
size_t index) {
1780 auto type = getElementType(index);
1782 return TypeSwitch<FIRRTLType, ElementType>(type)
1783 .Case<
FIRRTLBaseType, OpenBundleType, OpenVectorType>([&](
auto type) {
1784 return type.getConstType(type.isConst() ||
isConst());
1790 OpenBundleType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
1791 ArrayRef<BundleElement> elements,
bool isConst) {
1792 for (
auto &element : elements) {
1794 return emitErrorFn()
1795 <<
"'const' bundle cannot have references, but element "
1796 << element.name <<
" has type " << element.type;
1808 using KeyTy = std::tuple<FIRRTLBaseType, size_t, char>;
1826 static_cast<bool>(std::get<2>(key)));
1845 return getImpl()->elementType;
1848 size_t FVectorType::getNumElements()
const {
return getImpl()->numElements; }
1852 return getImpl()->props;
1857 auto *impl = getImpl();
1860 if (impl->passiveType)
1861 return impl->passiveType;
1864 if (impl->elementType.getRecursiveTypeProperties().isPassive)
1865 return impl->passiveType = *
this;
1870 impl->passiveType = passiveType;
1874 FVectorType FVectorType::getConstType(
bool isConst) {
1877 return get(getElementType(), getNumElements(),
isConst);
1880 FVectorType FVectorType::getAllConstDroppedType() {
1883 return get(getElementType().getAllConstDroppedType(), getNumElements(),
1889 auto *impl = getImpl();
1891 if (impl->anonymousType)
1892 return impl->anonymousType;
1895 if (!impl->props.containsTypeAlias)
1896 return impl->anonymousType = *
this;
1901 impl->anonymousType = anonymousType;
1902 return anonymousType;
1910 assert(fieldID &&
"fieldID must be at least 1");
1915 std::pair<uint64_t, uint64_t>
1919 return {index, fieldID - elementFieldID};
1922 std::pair<Type, uint64_t>
1930 return getNumElements() *
1934 std::pair<uint64_t, bool>
1939 return std::make_pair(fieldID - childRoot,
1940 fieldID >= childRoot && fieldID <= rangeEnd);
1945 FVectorType::ElementType FVectorType::getElementTypePreservingConst() {
1946 auto type = getElementType();
1947 return type.getConstType(type.isConst() ||
isConst());
1955 using KeyTy = std::tuple<FIRRTLType, size_t, char>;
1973 static_cast<bool>(std::get<2>(key)));
1988 FIRRTLType OpenVectorType::getElementType()
const {
1989 return getImpl()->elementType;
1992 size_t OpenVectorType::getNumElements()
const {
return getImpl()->numElements; }
1996 return getImpl()->props;
1999 OpenVectorType OpenVectorType::getConstType(
bool isConst) {
2002 return get(getElementType(), getNumElements(),
isConst);
2010 assert(fieldID &&
"fieldID must be at least 1");
2015 std::pair<uint64_t, uint64_t>
2019 return {index, fieldID - elementFieldID};
2022 std::pair<Type, uint64_t>
2031 return getNumElements() *
2035 std::pair<uint64_t, bool>
2040 return std::make_pair(fieldID - childRoot,
2041 fieldID >= childRoot && fieldID <= rangeEnd);
2046 OpenVectorType::ElementType OpenVectorType::getElementTypePreservingConst() {
2047 auto type = getElementType();
2049 return TypeSwitch<FIRRTLType, ElementType>(type)
2050 .Case<
FIRRTLBaseType, OpenBundleType, OpenVectorType>([&](
auto type) {
2051 return type.getConstType(type.isConst() ||
isConst());
2057 OpenVectorType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
2061 return emitErrorFn() <<
"vector cannot be const with references";
2070 using KeyTy = std::pair<ArrayRef<FEnumType::EnumElement>,
char>;
2076 false,
false,
false};
2077 uint64_t fieldID = 0;
2080 auto type = element.type;
2081 auto eltInfo = type.getRecursiveTypeProperties();
2082 props.isPassive &= eltInfo.isPassive;
2083 props.containsAnalog |= eltInfo.containsAnalog;
2084 props.containsConst |= eltInfo.containsConst;
2085 props.containsReference |= eltInfo.containsReference;
2086 props.containsTypeAlias |= eltInfo.containsTypeAlias;
2087 props.hasUninferredReset |= eltInfo.hasUninferredReset;
2088 props.hasUninferredWidth |= eltInfo.hasUninferredWidth;
2103 return llvm::hash_combine(
2104 llvm::hash_combine_range(key.first.begin(), key.first.end()),
2123 ArrayRef<EnumElement> elements,
bool isConst) {
2127 ArrayRef<FEnumType::EnumElement> FEnumType::getElements()
const {
2128 return getImpl()->elements;
2131 FEnumType FEnumType::getConstType(
bool isConst) {
2132 return get(getContext(), getElements(),
isConst);
2135 FEnumType FEnumType::getAllConstDroppedType() {
2139 SmallVector<EnumElement> constDroppedElements(
2140 llvm::map_range(getElements(), [](EnumElement element) {
2141 element.type = element.type.getAllConstDroppedType();
2144 return get(getContext(), constDroppedElements,
false);
2149 return getImpl()->recProps;
2152 std::optional<unsigned> FEnumType::getElementIndex(StringAttr name) {
2153 for (
const auto &it : llvm::enumerate(getElements())) {
2154 auto element = it.value();
2155 if (element.name == name) {
2156 return unsigned(it.index());
2159 return std::nullopt;
2162 std::optional<unsigned> FEnumType::getElementIndex(StringRef name) {
2163 for (
const auto &it : llvm::enumerate(getElements())) {
2164 auto element = it.value();
2165 if (element.name.getValue() == name) {
2166 return unsigned(it.index());
2169 return std::nullopt;
2172 StringAttr FEnumType::getElementNameAttr(
size_t index) {
2173 assert(index < getNumElements() &&
2174 "index must be less than number of fields in enum");
2175 return getElements()[index].name;
2178 StringRef FEnumType::getElementName(
size_t index) {
2179 return getElementNameAttr(index).getValue();
2182 std::optional<FEnumType::EnumElement> FEnumType::getElement(StringAttr name) {
2183 if (
auto maybeIndex = getElementIndex(name))
2184 return getElements()[*maybeIndex];
2185 return std::nullopt;
2188 std::optional<FEnumType::EnumElement> FEnumType::getElement(StringRef name) {
2189 if (
auto maybeIndex = getElementIndex(name))
2190 return getElements()[*maybeIndex];
2191 return std::nullopt;
2195 FEnumType::EnumElement FEnumType::getElement(
size_t index) {
2196 assert(index < getNumElements() &&
2197 "index must be less than number of fields in enum");
2198 return getElements()[index];
2202 auto element = getElement(name);
2207 auto element = getElement(name);
2212 assert(index < getNumElements() &&
2213 "index must be less than number of fields in enum");
2214 return getElements()[index].type;
2217 FIRRTLBaseType FEnumType::getElementTypePreservingConst(
size_t index) {
2218 auto type = getElementType(index);
2219 return type.getConstType(type.isConst() ||
isConst());
2223 return getImpl()->fieldIDs[index];
2227 assert(!getElements().
empty() &&
"Enum must have >0 fields");
2228 auto fieldIDs = getImpl()->fieldIDs;
2229 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
2230 return std::distance(fieldIDs.begin(), it);
2233 std::pair<uint64_t, uint64_t>
2237 return {index, fieldID - elementFieldID};
2240 std::pair<Type, uint64_t>
2245 auto subfieldType = getElementType(subfieldIndex);
2246 auto subfieldID = fieldID -
getFieldID(subfieldIndex);
2247 return {subfieldType, subfieldID};
2252 std::pair<uint64_t, bool>
2255 auto rangeEnd = index + 1 >= getNumElements() ?
getMaxFieldID()
2257 return std::make_pair(fieldID - childRoot,
2258 fieldID >= childRoot && fieldID <= rangeEnd);
2261 auto FEnumType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
2262 ArrayRef<EnumElement> elements,
bool isConst)
2264 for (
auto &elt : elements) {
2265 auto r = elt.type.getRecursiveTypeProperties();
2267 return emitErrorFn() <<
"enum field '" << elt.name <<
"' not passive";
2268 if (r.containsAnalog)
2269 return emitErrorFn() <<
"enum field '" << elt.name <<
"' contains analog";
2270 if (r.containsConst && !
isConst)
2271 return emitErrorFn() <<
"enum with 'const' elements must be 'const'";
2279 auto *impl = getImpl();
2281 if (impl->anonymousType)
2282 return impl->anonymousType;
2284 if (!impl->recProps.containsTypeAlias)
2285 return impl->anonymousType = *
this;
2287 SmallVector<FEnumType::EnumElement, 4> elements;
2289 for (
auto element : getElements())
2290 elements.push_back({element.name, element.type.getAnonymousType()});
2291 return impl->anonymousType =
FEnumType::get(getContext(), elements);
2300 using KeyTy = std::tuple<StringAttr, FIRRTLBaseType>;
2311 return llvm::hash_combine(key);
2325 -> BaseTypeAliasType {
2330 return getImpl()->name;
2334 return getImpl()->innerType;
2338 auto *impl = getImpl();
2339 if (impl->anonymousType)
2340 return impl->anonymousType;
2341 return impl->anonymousType = getInnerType().getAnonymousType();
2349 auto rtp = getInnerType().getRecursiveTypeProperties();
2357 if (newInnerType == getInnerType())
2359 return newInnerType;
2364 return getModifiedType(getInnerType().getAllConstDroppedType());
2368 return getModifiedType(getInnerType().getConstType(
isConst));
2371 std::pair<Type, uint64_t>
2380 std::pair<uint64_t, bool>
2382 uint64_t index)
const {
2394 std::pair<uint64_t, uint64_t>
2404 return Base::get(type.getContext(), type, forceable);
2407 auto RefType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
2409 if (!base.isPassive())
2410 return emitErrorFn() <<
"reference base type must be passive";
2411 if (forceable && base.containsConst())
2412 return emitErrorFn()
2413 <<
"forceable reference base type cannot contain const";
2418 auto rtp = getType().getRecursiveTypeProperties();
2421 rtp.isPassive =
false;
2438 LogicalResult AnalogType::verify(function_ref<InFlightDiagnostic()> emitError,
2439 int32_t widthOrSentinel,
bool isConst) {
2440 if (widthOrSentinel < -1)
2441 return emitError() <<
"invalid width";
2445 int32_t AnalogType::getWidthOrSentinel()
const {
return getImpl()->width; }
2447 AnalogType AnalogType::getConstType(
bool isConst) {
2450 return get(getContext(), getWidthOrSentinel(),
isConst);
2457 ClockType ClockType::getConstType(
bool isConst) {
2467 ResetType ResetType::getConstType(
bool isConst) {
2477 AsyncResetType AsyncResetType::getConstType(
bool isConst) {
2488 using KeyTy = std::pair<FlatSymbolRefAttr, ArrayRef<ClassElement>>;
2492 auto name = key.first;
2493 auto elements = allocator.copyInto(key.second);
2496 SmallVector<uint64_t, 4> ids;
2505 auto fieldIDs = allocator.copyInto(ArrayRef(ids));
2528 ArrayRef<ClassElement> elements) {
2529 return get(name.getContext(), name, elements);
2533 return getNameAttr().getAttr().getValue();
2536 FlatSymbolRefAttr ClassType::getNameAttr()
const {
return getImpl()->name; }
2538 ArrayRef<ClassElement> ClassType::getElements()
const {
2539 return getImpl()->elements;
2542 const ClassElement &ClassType::getElement(IntegerAttr index)
const {
2543 return getElement(index.getValue().getZExtValue());
2546 const ClassElement &ClassType::getElement(
size_t index)
const {
2547 return getElements()[index];
2550 std::optional<uint64_t> ClassType::getElementIndex(StringRef fieldName)
const {
2551 for (
const auto [i, e] : llvm::enumerate(getElements()))
2552 if (fieldName == e.name)
2557 void ClassType::printInterface(AsmPrinter &p)
const {
2561 for (
const auto &element : getElements()) {
2565 p.printKeywordOrString(element.name);
2566 p <<
": " << element.type;
2573 return getImpl()->fieldIDs[index];
2577 assert(!getElements().
empty() &&
"Class must have >0 fields");
2578 auto fieldIDs = getImpl()->fieldIDs;
2579 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
2580 return std::distance(fieldIDs.begin(), it);
2583 std::pair<uint64_t, uint64_t>
2587 return {index, fieldID - elementFieldID};
2590 std::pair<Type, uint64_t>
2595 auto subfieldType = getElement(subfieldIndex).type;
2596 auto subfieldID = fieldID -
getFieldID(subfieldIndex);
2597 return {subfieldType, subfieldID};
2602 std::pair<uint64_t, bool>
2605 auto rangeEnd = index + 1 >= getNumElements() ?
getMaxFieldID()
2607 return std::make_pair(fieldID - childRoot,
2608 fieldID >= childRoot && fieldID <= rangeEnd);
2611 ParseResult ClassType::parseInterface(AsmParser &parser, ClassType &result) {
2612 StringAttr className;
2613 if (parser.parseSymbolName(className))
2616 SmallVector<ClassElement> elements;
2617 if (parser.parseCommaSeparatedList(
2618 OpAsmParser::Delimiter::Paren, [&]() -> ParseResult {
2620 Direction direction;
2621 if (succeeded(parser.parseOptionalKeyword(
"out")))
2622 direction = Direction::Out;
2623 else if (succeeded(parser.parseKeyword(
"in",
"or 'out'")))
2624 direction = Direction::In;
2629 std::string keyword;
2630 if (parser.parseKeywordOrString(&keyword))
2632 StringAttr name = StringAttr::get(parser.getContext(), keyword);
2636 if (parser.parseColonType(type))
2639 elements.emplace_back(name, type, direction);
2652 void FIRRTLDialect::registerTypes() {
2654 #define GET_TYPEDEF_LIST
2655 #include "circt/Dialect/FIRRTL/FIRRTLTypes.cpp.inc"
2669 return TypeSwitch<FIRRTLBaseType, std::optional<int64_t>>(type)
2670 .Case<BundleType>([&](BundleType bundle) -> std::optional<int64_t> {
2672 for (
auto &elt : bundle) {
2673 if (elt.isFlip && !ignoreFlip)
2674 return std::nullopt;
2677 return std::nullopt;
2682 .Case<FEnumType>([&](FEnumType fenum) -> std::optional<int64_t> {
2684 for (
auto &elt : fenum) {
2687 return std::nullopt;
2690 return width + llvm::Log2_32_Ceil(fenum.getNumElements());
2692 .Case<FVectorType>([&](
auto vector) -> std::optional<int64_t> {
2695 return std::nullopt;
2696 return *w * vector.getNumElements();
2699 .Case<ClockType, ResetType, AsyncResetType>([](Type) {
return 1; })
2700 .Default([&](
auto t) {
return std::nullopt; });
assert(baseType &&"element must be base type")
MlirType uint64_t numElements
static ParseResult parseFIRRTLBaseType(FIRRTLBaseType &result, StringRef name, AsmParser &parser)
static ParseResult parseFIRRTLPropertyType(PropertyType &result, StringRef name, AsmParser &parser)
static LogicalResult customTypePrinter(Type type, AsmPrinter &os)
Print a type with a custom printer implementation.
static OptionalParseResult customTypeParser(AsmParser &parser, StringRef name, Type &result)
Parse a type with a custom parser implementation.
static ParseResult parseType(Type &result, StringRef name, AsmParser &parser)
Parse a type defined by this dialect.
@ ContainsAnalogBitMask
Bit set if the type contains an analog type.
@ HasUninferredWidthBitMask
Bit set fi the type has any uninferred bit widths.
@ IsPassiveBitMask
Bit set if the type only contains passive elements.
static bool areBundleElementsEquivalent(BundleType::BundleElement destElement, BundleType::BundleElement srcElement, bool destOuterTypeIsConst, bool srcOuterTypeIsConst, bool requiresSameWidth)
Helper to implement the equivalence logic for a pair of bundle elements.
static ParseResult parseFIRRTLType(FIRRTLType &result, StringRef name, AsmParser &parser)
Parse a FIRRTLType with a name that has already been parsed.
static unsigned getIndexForFieldID(BundleType type, unsigned fieldID)
static unsigned getMaxFieldID(FIRRTLBaseType type)
static InstancePath empty
FIRRTLBaseType getAnonymousType()
Return this type with any type alias types recursively removed from itself.
bool isResetType()
Return true if this is a valid "reset" type.
FIRRTLBaseType getMaskType()
Return this type with all ground types replaced with UInt<1>.
FIRRTLBaseType getPassiveType()
Return this type with any flip types recursively removed from itself.
int32_t getBitWidthOrSentinel()
If this is an IntType, AnalogType, or sugar type for a single bit (Clock, Reset, etc) then return the...
bool isConst()
Returns true if this is a 'const' type that can only hold compile-time constant values.
FIRRTLBaseType getAllConstDroppedType()
Return this type with a 'const' modifiers dropped.
FIRRTLBaseType getConstType(bool isConst)
Return a 'const' or non-'const' version of this type.
FIRRTLBaseType getWidthlessType()
Return this type with widths of all ground types removed.
bool containsReference()
Return true if this is or contains a Reference type.
bool isGround()
Return true if this is a 'ground' type, aka a non-aggregate type.
bool isConst()
Returns true if this is a 'const' type that can only hold compile-time constant values.
RecursiveTypeProperties getRecursiveTypeProperties() const
Return the recursive properties of the type, containing the isPassive, containsAnalog,...
This is the common base class between SIntType and UIntType.
int32_t getWidthOrSentinel() const
Return the width of this type, or -1 if it has none specified.
static IntType get(MLIRContext *context, bool isSigned, int32_t widthOrSentinel=-1, bool isConst=false)
Return an SIntType or UIntType with the specified signedness, width, and constness.
IntType getConstType(bool isConst)
Return a 'const' or non-'const' version of this type.
std::optional< int32_t > getWidth() const
Return an optional containing the width, if the width is known (or empty if width is unknown).
Represents a limited word-length unsigned integer in SystemC as described in IEEE 1666-2011 ยง7....
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
uint64_t getWidth(Type t)
mlir::Type innerType(mlir::Type type)
ParseResult parseNestedType(FIRRTLType &result, AsmParser &parser)
Parse a FIRRTLType.
bool areAnonymousTypesEquivalent(FIRRTLBaseType lhs, FIRRTLBaseType rhs)
Return true if anonymous types of given arguments are equivalent by pointer comparison.
ParseResult parseNestedBaseType(FIRRTLBaseType &result, AsmParser &parser)
bool isTypeInOut(mlir::Type type)
Returns true if the given type has some flipped (aka unaligned) dataflow.
bool areTypesRefCastable(Type dstType, Type srcType)
Return true if destination ref type can be cast from source ref type, per FIRRTL spec rules they must...
bool areTypesEquivalent(FIRRTLType destType, FIRRTLType srcType, bool destOuterTypeIsConst=false, bool srcOuterTypeIsConst=false, bool requireSameWidths=false)
Returns whether the two types are equivalent.
bool areTypesWeaklyEquivalent(FIRRTLType destType, FIRRTLType srcType, bool destFlip=false, bool srcFlip=false, bool destOuterTypeIsConst=false, bool srcOuterTypeIsConst=false)
Returns true if two types are weakly equivalent.
mlir::Type getPassiveType(mlir::Type anyBaseFIRRTLType)
bool isTypeLarger(FIRRTLBaseType dstType, FIRRTLBaseType srcType)
Returns true if the destination is at least as wide as a source.
bool containsConst(Type type)
Returns true if the type is or contains a 'const' type whose value is guaranteed to be unchanging at ...
void printNestedType(Type type, AsmPrinter &os)
Print a type defined by this dialect.
bool isConst(Type type)
Returns true if this is a 'const' type whose value is guaranteed to be unchanging at circuit executio...
bool areTypesConstCastable(FIRRTLType destType, FIRRTLType srcType, bool srcOuterTypeIsConst=false)
Returns whether the srcType can be const-casted to the destType.
ParseResult parseNestedPropertyType(PropertyType &result, AsmParser &parser)
std::optional< int64_t > getBitWidth(FIRRTLBaseType type, bool ignoreFlip=false)
std::pair< uint64_t, uint64_t > getIndexAndSubfieldID(Type type, uint64_t fieldID)
uint64_t getFieldID(Type type, uint64_t index)
std::pair<::mlir::Type, uint64_t > getSubTypeByFieldID(Type, uint64_t fieldID)
std::pair< uint64_t, bool > projectToChildFieldID(Type, uint64_t fieldID, uint64_t index)
uint64_t getIndexForFieldID(Type type, uint64_t fieldID)
uint64_t getMaxFieldID(Type)
StringAttr getName(ArrayAttr names, size_t idx)
Return the name at the specified index of the ArrayAttr or null if it cannot be determined.
This file defines an intermediate representation for circuits acting as an abstraction for constraint...
A collection of bits indicating the recursive properties of a type.
bool containsReference
Whether the type contains a reference type.
bool isPassive
Whether the type only contains passive elements.
bool containsAnalog
Whether the type contains an analog type.
bool hasUninferredReset
Whether the type has any uninferred reset.
bool containsTypeAlias
Whether the type contains a type alias.
bool containsConst
Whether the type contains a const type.
bool hasUninferredWidth
Whether the type has any uninferred bit widths.
bool operator==(const KeyTy &key) const
static BaseTypeAliasStorage * construct(TypeStorageAllocator &allocator, KeyTy key)
BaseTypeAliasStorage(StringAttr name, FIRRTLBaseType innerType)
std::tuple< StringAttr, FIRRTLBaseType > KeyTy
static llvm::hash_code hashKey(const KeyTy &key)
FIRRTLBaseType anonymousType
SmallVector< BundleType::BundleElement, 4 > elements
static BundleTypeStorage * construct(TypeStorageAllocator &allocator, KeyTy key)
std::pair< ArrayRef< BundleType::BundleElement >, char > KeyTy
static llvm::hash_code hashKey(const KeyTy &key)
RecursiveTypeProperties props
This holds the bits for the type's recursive properties, and can hold a pointer to a passive version ...
BundleTypeStorage(ArrayRef< BundleType::BundleElement > elements, bool isConst)
bool operator==(const KeyTy &key) const
SmallVector< uint64_t, 4 > fieldIDs
std::pair< FlatSymbolRefAttr, ArrayRef< ClassElement > > KeyTy
bool operator==(const KeyTy &key) const
static ClassTypeStorage * construct(TypeStorageAllocator &allocator, KeyTy key)
ArrayRef< uint64_t > fieldIDs
ArrayRef< ClassElement > elements
ClassTypeStorage(FlatSymbolRefAttr name, ArrayRef< ClassElement > elements, ArrayRef< uint64_t > fieldIDs, uint64_t maxFieldID)
SmallVector< FEnumType::EnumElement, 4 > elements
static llvm::hash_code hashKey(const KeyTy &key)
bool operator==(const KeyTy &key) const
FEnumTypeStorage(ArrayRef< FEnumType::EnumElement > elements, bool isConst)
std::pair< ArrayRef< FEnumType::EnumElement >, char > KeyTy
RecursiveTypeProperties recProps
FIRRTLBaseType anonymousType
static FEnumTypeStorage * construct(TypeStorageAllocator &allocator, KeyTy key)
SmallVector< uint64_t, 4 > fieldIDs
static FIRRTLBaseTypeStorage * construct(TypeStorageAllocator &allocator, KeyTy key)
bool operator==(const KeyTy &key) const
FIRRTLBaseTypeStorage(bool isConst)
bool operator==(const KeyTy &key) const
FIRRTLBaseType elementType
RecursiveTypeProperties props
This holds the bits for the type's recursive properties, and can hold a pointer to a passive version ...
FIRRTLBaseType passiveType
FIRRTLBaseType anonymousType
static FVectorTypeStorage * construct(TypeStorageAllocator &allocator, KeyTy key)
std::tuple< FIRRTLBaseType, size_t, char > KeyTy
FVectorTypeStorage(FIRRTLBaseType elementType, size_t numElements, bool isConst)
SmallVector< OpenBundleType::BundleElement, 4 > elements
static OpenBundleTypeStorage * construct(TypeStorageAllocator &allocator, KeyTy key)
bool operator==(const KeyTy &key) const
static llvm::hash_code hashKey(const KeyTy &key)
RecursiveTypeProperties props
This holds the bits for the type's recursive properties, and can hold a pointer to a passive version ...
OpenBundleTypeStorage(ArrayRef< OpenBundleType::BundleElement > elements, bool isConst)
SmallVector< uint64_t, 4 > fieldIDs
std::pair< ArrayRef< OpenBundleType::BundleElement >, char > KeyTy
std::tuple< FIRRTLType, size_t, char > KeyTy
bool operator==(const KeyTy &key) const
RecursiveTypeProperties props
OpenVectorTypeStorage(FIRRTLType elementType, size_t numElements, bool isConst)
static OpenVectorTypeStorage * construct(TypeStorageAllocator &allocator, KeyTy key)
WidthTypeStorage(int32_t width, bool isConst)
static WidthTypeStorage * construct(TypeStorageAllocator &allocator, const KeyTy &key)
bool operator==(const KeyTy &key) const
std::pair< int32_t, char > KeyTy