17#include "mlir/IR/DialectImplementation.h"
18#include "llvm/ADT/StringExtras.h"
19#include "llvm/ADT/StringSwitch.h"
20#include "llvm/ADT/TypeSwitch.h"
23using namespace firrtl;
25using mlir::OptionalParseResult;
26using mlir::TypeStorageAllocator;
33#define GET_TYPEDEF_CLASSES
34#include "circt/Dialect/FIRRTL/FIRRTLTypes.cpp.inc"
49 auto printWidthQualifier = [&](std::optional<int32_t> width) {
51 os <<
'<' << *width <<
'>';
53 bool anyFailed =
false;
54 TypeSwitch<Type>(type)
55 .Case<ClockType>([&](
auto) { os <<
"clock"; })
56 .Case<ResetType>([&](
auto) { os <<
"reset"; })
57 .Case<AsyncResetType>([&](
auto) { os <<
"asyncreset"; })
58 .Case<SIntType>([&](
auto sIntType) {
60 printWidthQualifier(sIntType.getWidth());
62 .Case<UIntType>([&](
auto uIntType) {
64 printWidthQualifier(uIntType.getWidth());
66 .Case<AnalogType>([&](
auto analogType) {
68 printWidthQualifier(analogType.getWidth());
70 .Case<BundleType, OpenBundleType>([&](
auto bundleType) {
71 if (firrtl::type_isa<OpenBundleType>(bundleType))
74 llvm::interleaveComma(bundleType, os, [&](
auto element) {
75 StringRef fieldName = element.name.getValue();
76 bool isLiteralIdentifier =
77 !fieldName.empty() && llvm::isDigit(fieldName.front());
78 if (isLiteralIdentifier)
80 os << element.name.getValue();
81 if (isLiteralIdentifier)
90 .Case<FEnumType>([&](
auto fenumType) {
92 llvm::interleaveComma(fenumType, os,
93 [&](FEnumType::EnumElement element) {
94 os << element.name.getValue();
100 .Case<FVectorType, OpenVectorType>([&](
auto vectorType) {
101 if (firrtl::type_isa<OpenVectorType>(vectorType))
105 os <<
", " << vectorType.getNumElements() <<
'>';
107 .Case<RefType>([&](RefType refType) {
108 if (refType.getForceable())
112 if (
auto layer = refType.getLayer())
116 .Case<LHSType>([&](LHSType lhstype) {
121 .Case<StringType>([&](
auto stringType) { os <<
"string"; })
122 .Case<FIntegerType>([&](
auto integerType) { os <<
"integer"; })
123 .Case<BoolType>([&](
auto boolType) { os <<
"bool"; })
124 .Case<DoubleType>([&](
auto doubleType) { os <<
"double"; })
125 .Case<ListType>([&](
auto listType) {
130 .Case<PathType>([&](
auto pathType) { os <<
"path"; })
131 .Case<BaseTypeAliasType>([&](BaseTypeAliasType alias) {
132 os <<
"alias<" << alias.getName().getValue() <<
", ";
136 .Case<ClassType>([&](ClassType type) {
138 type.printInterface(os);
141 .Case<AnyRefType>([&](AnyRefType type) { os <<
"anyref"; })
142 .Case<FStringType>([&](
auto) { os <<
"fstring"; })
143 .Default([&](
auto) { anyFailed =
true; });
144 return failure(anyFailed);
155 assert(
false &&
"type to print unknown to FIRRTL dialect");
190 const char constPrefix[] =
"const.";
191 if (name.starts_with(constPrefix)) {
193 name = name.drop_front(std::size(constPrefix) - 1);
196 auto *context = parser.getContext();
198 return result = ClockType::get(context,
isConst), success();
200 return result = ResetType::get(context,
isConst), success();
201 if (name ==
"asyncreset")
202 return result = AsyncResetType::get(context,
isConst), success();
204 if (name ==
"sint" || name ==
"uint" || name ==
"analog") {
207 if (!parser.parseOptionalLess()) {
208 if (parser.parseInteger(width) || parser.parseGreater())
212 return parser.emitError(parser.getNameLoc(),
"unknown width"),
217 result = SIntType::get(context, width,
isConst);
218 else if (name ==
"uint")
219 result = UIntType::get(context, width,
isConst);
222 result = AnalogType::get(context, width,
isConst);
227 if (name ==
"bundle") {
228 SmallVector<BundleType::BundleElement, 4> elements;
230 auto parseBundleElement = [&]() -> ParseResult {
235 if (failed(parser.parseKeywordOrString(&nameStr)))
239 bool isFlip = succeeded(parser.parseOptionalKeyword(
"flip"));
243 elements.push_back({StringAttr::get(context, name), isFlip, type});
247 if (parser.parseCommaSeparatedList(mlir::AsmParser::Delimiter::LessGreater,
251 return result = BundleType::get(context, elements,
isConst), success();
253 if (name ==
"openbundle") {
254 SmallVector<OpenBundleType::BundleElement, 4> elements;
256 auto parseBundleElement = [&]() -> ParseResult {
261 if (failed(parser.parseKeywordOrString(&nameStr)))
265 bool isFlip = succeeded(parser.parseOptionalKeyword(
"flip"));
269 elements.push_back({StringAttr::get(context, name), isFlip, type});
273 if (parser.parseCommaSeparatedList(mlir::AsmParser::Delimiter::LessGreater,
277 result = parser.getChecked<OpenBundleType>(context, elements,
isConst);
278 return failure(!result);
281 if (name ==
"enum") {
282 SmallVector<FEnumType::EnumElement, 4> elements;
284 auto parseEnumElement = [&]() -> ParseResult {
289 if (failed(parser.parseKeywordOrString(&nameStr)))
296 elements.push_back({StringAttr::get(context, name), type});
300 if (parser.parseCommaSeparatedList(mlir::AsmParser::Delimiter::LessGreater,
303 if (failed(FEnumType::verify(
304 [&]() {
return parser.emitError(parser.getNameLoc()); }, elements,
308 return result = FEnumType::get(context, elements,
isConst), success();
311 if (name ==
"vector") {
316 parser.parseComma() || parser.parseInteger(width) ||
317 parser.parseGreater())
322 if (name ==
"openvector") {
327 parser.parseComma() || parser.parseInteger(width) ||
328 parser.parseGreater())
333 return failure(!result);
337 if (name ==
"ref" || name ==
"probe") {
344 if (parser.parseOptionalComma().succeeded())
345 if (parser.parseOptionalAttribute(layer).value())
346 return parser.emitError(parser.getNameLoc(),
347 "expected symbol reference");
348 if (parser.parseGreater())
351 if (failed(RefType::verify(
352 [&]() {
return parser.emitError(parser.getNameLoc()); }, type,
356 return result = RefType::get(type,
false, layer), success();
361 parser.parseGreater())
363 if (!isa<FIRRTLBaseType>(type))
364 return parser.emitError(parser.getNameLoc(),
"expected base type");
365 result = parser.getChecked<LHSType>(context, cast<FIRRTLBaseType>(type));
366 return failure(!result);
368 if (name ==
"rwprobe") {
373 if (parser.parseOptionalComma().succeeded())
374 if (parser.parseOptionalAttribute(layer).value())
375 return parser.emitError(parser.getNameLoc(),
376 "expected symbol reference");
377 if (parser.parseGreater())
380 if (failed(RefType::verify(
381 [&]() {
return parser.emitError(parser.getNameLoc()); }, type,
true,
385 return result = RefType::get(type,
true, layer), success();
387 if (name ==
"class") {
389 return parser.emitError(parser.getNameLoc(),
"classes cannot be const");
391 if (parser.parseLess() || ClassType::parseInterface(parser, classType) ||
392 parser.parseGreater())
397 if (name ==
"anyref") {
399 return parser.emitError(parser.getNameLoc(),
"any refs cannot be const");
401 result = AnyRefType::get(parser.getContext());
404 if (name ==
"string") {
406 parser.emitError(parser.getNameLoc(),
"strings cannot be const");
409 result = StringType::get(parser.getContext());
412 if (name ==
"integer") {
414 parser.emitError(parser.getNameLoc(),
"bigints cannot be const");
417 result = FIntegerType::get(parser.getContext());
420 if (name ==
"bool") {
422 parser.emitError(parser.getNameLoc(),
"bools cannot be const");
425 result = BoolType::get(parser.getContext());
428 if (name ==
"double") {
430 parser.emitError(parser.getNameLoc(),
"doubles cannot be const");
433 result = DoubleType::get(parser.getContext());
436 if (name ==
"list") {
438 parser.emitError(parser.getNameLoc(),
"lists cannot be const");
443 parser.parseGreater())
445 result = parser.getChecked<ListType>(context,
elementType);
450 if (name ==
"path") {
452 parser.emitError(parser.getNameLoc(),
"path cannot be const");
455 result = PathType::get(parser.getContext());
458 if (name ==
"alias") {
461 if (parser.parseLess() || parser.parseKeyword(&name) ||
463 parser.parseGreater())
467 BaseTypeAliasType::get(StringAttr::get(context, name), type),
470 if (name ==
"fstring") {
471 return result = FStringType::get(context), success();
482static ParseResult
parseType(Type &result, StringRef name, AsmParser &parser) {
485 if (parseResult.has_value())
486 return parseResult.value();
489 parser.emitError(parser.getNameLoc(),
"unknown FIRRTL dialect type: \"")
482static ParseResult
parseType(Type &result, StringRef name, AsmParser &parser) {
…}
501 if (failed(
parseType(type, name, parser)))
503 result = type_dyn_cast<FIRRTLType>(type);
506 parser.emitError(parser.getNameLoc(),
"unknown FIRRTL type: \"")
516 if (
auto base = type_dyn_cast<FIRRTLBaseType>(type)) {
520 parser.emitError(parser.getNameLoc(),
"expected base type, found ") << type;
529 if (
auto prop = type_dyn_cast<PropertyType>(type)) {
533 parser.emitError(parser.getNameLoc(),
"expected property type, found ")
546 if (parser.parseKeyword(&name))
556 if (parser.parseKeyword(&name))
566 if (parser.parseKeyword(&name))
577void FIRRTLDialect::printType(Type type, DialectAsmPrinter &os)
const {
582Type FIRRTLDialect::parseType(DialectAsmParser &parser)
const {
585 if (parser.parseKeyword(&name) ||
::parseType(result, name, parser))
628bool FIRRTLType::isGround() {
629 return TypeSwitch<FIRRTLType, bool>(*
this)
630 .Case<ClockType, ResetType, AsyncResetType, SIntType, UIntType,
631 AnalogType>([](Type) {
return true; })
632 .Case<BundleType, FVectorType, FEnumType, OpenBundleType, OpenVectorType>(
633 [](Type) {
return false; })
634 .Case<BaseTypeAliasType>([](BaseTypeAliasType alias) {
635 return alias.getAnonymousType().isGround();
638 .Case<PropertyType, RefType>([](Type) {
return false; })
640 llvm_unreachable(
"unknown FIRRTL type");
646 return TypeSwitch<FIRRTLType, bool>(*
this)
648 [](
auto type) {
return type.isConst(); })
655 return TypeSwitch<FIRRTLType, RecursiveTypeProperties>(*
this)
656 .Case<ClockType, ResetType, AsyncResetType>([](
FIRRTLBaseType type) {
663 firrtl::type_isa<ResetType>(type)};
665 .Case<SIntType, UIntType>([](
auto type) {
667 true,
false,
false, type.isConst(),
false, !type.hasWidth(),
false};
669 .Case<AnalogType>([](
auto type) {
671 true,
false,
true, type.isConst(),
false, !type.hasWidth(),
false};
673 .Case<BundleType, FVectorType, FEnumType, OpenBundleType, OpenVectorType,
674 RefType, BaseTypeAliasType>(
675 [](
auto type) {
return type.getRecursiveTypeProperties(); })
676 .Case<PropertyType>([](
auto type) {
678 false,
false,
false};
681 [](
auto type) {
return type.getType().getRecursiveTypeProperties(); })
682 .Case<FStringType>([](
auto type) {
684 false,
false,
false};
687 llvm_unreachable(
"unknown FIRRTL type");
694 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
695 .Case<ClockType, ResetType, AsyncResetType, SIntType, UIntType,
696 AnalogType>([&](Type) {
return *
this; })
697 .Case<BundleType, FVectorType, FEnumType, BaseTypeAliasType>(
698 [](
auto type) {
return type.getAnonymousType(); })
700 llvm_unreachable(
"unknown FIRRTL type");
707 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
708 .Case<ClockType, ResetType, AsyncResetType, SIntType, UIntType,
709 AnalogType, FEnumType>([&](Type) {
return *
this; })
710 .Case<BundleType, FVectorType, FEnumType, BaseTypeAliasType>(
711 [](
auto type) {
return type.getPassiveType(); })
713 llvm_unreachable(
"unknown FIRRTL type");
720 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
721 .Case<ClockType, ResetType, AsyncResetType, AnalogType, SIntType,
722 UIntType, BundleType, FVectorType, FEnumType, BaseTypeAliasType>(
723 [&](
auto type) {
return type.getConstType(
isConst); })
725 llvm_unreachable(
"unknown FIRRTL type");
732 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
733 .Case<ClockType, ResetType, AsyncResetType, AnalogType, SIntType,
734 UIntType>([&](
auto type) {
return type.getConstType(
false); })
735 .Case<BundleType, FVectorType, FEnumType, BaseTypeAliasType>(
736 [&](
auto type) {
return type.getAllConstDroppedType(); })
738 llvm_unreachable(
"unknown FIRRTL type");
746 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
747 .Case<ClockType, ResetType, AsyncResetType, SIntType, UIntType,
748 AnalogType>([&](Type) {
749 return UIntType::get(this->getContext(), 1, this->
isConst());
751 .Case<BundleType>([&](BundleType bundleType) {
752 SmallVector<BundleType::BundleElement, 4> newElements;
753 newElements.reserve(bundleType.getElements().size());
754 for (
auto elt : bundleType)
755 newElements.push_back(
756 {elt.name,
false , elt.type.getMaskType()});
757 return BundleType::get(this->getContext(), newElements,
758 bundleType.isConst());
760 .Case<FVectorType>([](FVectorType vectorType) {
761 return FVectorType::get(vectorType.getElementType().getMaskType(),
762 vectorType.getNumElements(),
763 vectorType.isConst());
765 .Case<BaseTypeAliasType>([](BaseTypeAliasType base) {
766 return base.getModifiedType(base.getInnerType().getMaskType());
769 llvm_unreachable(
"unknown FIRRTL type");
777 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
778 .Case<ClockType, ResetType, AsyncResetType>([](
auto a) {
return a; })
779 .Case<UIntType, SIntType, AnalogType>(
780 [&](
auto a) {
return a.get(this->getContext(), -1, a.isConst()); })
781 .Case<BundleType>([&](
auto a) {
782 SmallVector<BundleType::BundleElement, 4> newElements;
783 newElements.reserve(a.getElements().size());
785 newElements.push_back(
786 {elt.name, elt.isFlip, elt.type.getWidthlessType()});
787 return BundleType::get(this->getContext(), newElements, a.isConst());
789 .Case<FVectorType>([](
auto a) {
790 return FVectorType::get(a.getElementType().getWidthlessType(),
791 a.getNumElements(), a.isConst());
793 .Case<FEnumType>([&](FEnumType a) {
794 SmallVector<FEnumType::EnumElement, 4> newElements;
795 newElements.reserve(a.getNumElements());
797 newElements.push_back({elt.name, elt.type.getWidthlessType()});
798 return FEnumType::get(this->getContext(), newElements, a.isConst());
800 .Case<BaseTypeAliasType>([](BaseTypeAliasType type) {
801 return type.getModifiedType(type.getInnerType().getWidthlessType());
804 llvm_unreachable(
"unknown FIRRTL type");
814 return TypeSwitch<FIRRTLBaseType, int32_t>(*
this)
815 .Case<ClockType, ResetType, AsyncResetType>([](Type) {
return 1; })
816 .Case<SIntType, UIntType>(
819 [](AnalogType analogType) {
return analogType.getWidthOrSentinel(); })
820 .Case<BundleType, FVectorType, FEnumType>([](Type) {
return -2; })
821 .Case<BaseTypeAliasType>([](BaseTypeAliasType type) {
823 return type.getAnonymousType().getBitWidthOrSentinel();
826 llvm_unreachable(
"unknown FIRRTL type");
835 return TypeSwitch<FIRRTLType, bool>(*
this)
836 .Case<ResetType, AsyncResetType>([](Type) {
return true; })
838 [](UIntType a) {
return !a.hasWidth() || a.getWidth() == 1; })
839 .Case<BaseTypeAliasType>(
840 [](
auto type) {
return type.getInnerType().isResetType(); })
841 .Default([](Type) {
return false; });
845 return TypeSwitch<Type, bool>(type)
847 [](
auto base) {
return base.isConst(); })
852 return TypeSwitch<Type, bool>(type)
854 [](
auto base) {
return base.containsConst(); })
861 .
Case<BundleType>([&](
auto bundle) {
862 for (
size_t i = 0, e = bundle.getNumElements(); i < e; ++i) {
863 auto elt = bundle.getElement(i);
867 return bundle.getNumElements() == 0;
869 .Case<FVectorType>([&](
auto vector) {
870 if (vector.getNumElements() == 0)
874 .Case<FIRRTLBaseType>([](
auto groundType) {
877 .Case<RefType>([](
auto ref) {
return hasZeroBitWidth(ref.getType()); })
878 .Default([](
auto) {
return false; });
888 BundleType::BundleElement srcElement,
889 bool destOuterTypeIsConst,
890 bool srcOuterTypeIsConst,
891 bool requiresSameWidth) {
892 if (destElement.name != srcElement.name)
894 if (destElement.isFlip != srcElement.isFlip)
897 if (destElement.isFlip) {
898 std::swap(destElement, srcElement);
899 std::swap(destOuterTypeIsConst, srcOuterTypeIsConst);
903 destOuterTypeIsConst, srcOuterTypeIsConst,
912 bool destOuterTypeIsConst,
913 bool srcOuterTypeIsConst,
914 bool requireSameWidths) {
915 auto destType = type_dyn_cast<FIRRTLBaseType>(destFType);
916 auto srcType = type_dyn_cast<FIRRTLBaseType>(srcFType);
919 if (!destType || !srcType)
920 return destFType == srcFType;
922 bool srcIsConst = srcOuterTypeIsConst || srcFType.
isConst();
923 bool destIsConst = destOuterTypeIsConst || destFType.
isConst();
926 auto destVectorType = type_dyn_cast<FVectorType>(destType);
927 auto srcVectorType = type_dyn_cast<FVectorType>(srcType);
928 if (destVectorType && srcVectorType)
929 return destVectorType.getNumElements() == srcVectorType.getNumElements() &&
931 srcVectorType.getElementType(), destIsConst,
932 srcIsConst, requireSameWidths);
936 auto destBundleType = type_dyn_cast<BundleType>(destType);
937 auto srcBundleType = type_dyn_cast<BundleType>(srcType);
938 if (destBundleType && srcBundleType) {
939 auto destElements = destBundleType.getElements();
940 auto srcElements = srcBundleType.getElements();
941 size_t numDestElements = destElements.size();
942 if (numDestElements != srcElements.size())
945 for (
size_t i = 0; i < numDestElements; ++i) {
946 auto destElement = destElements[i];
947 auto srcElement = srcElements[i];
949 srcIsConst, requireSameWidths))
957 auto dstEnumType = type_dyn_cast<FEnumType>(destType);
958 auto srcEnumType = type_dyn_cast<FEnumType>(srcType);
960 if (dstEnumType && srcEnumType) {
961 if (dstEnumType.getNumElements() != srcEnumType.getNumElements())
964 for (
const auto &[dst, src] : llvm::zip(dstEnumType, srcEnumType)) {
966 if (dst.name != src.name)
978 if (destIsConst && !srcIsConst)
982 if (firrtl::type_isa<ResetType>(destType))
983 return srcType.isResetType();
986 if (firrtl::type_isa<ResetType>(srcType))
987 return destType.isResetType();
991 if (!requireSameWidths || destType.getBitWidthOrSentinel() == -1)
992 srcType = srcType.getWidthlessType();
993 if (!requireSameWidths || srcType.getBitWidthOrSentinel() == -1)
994 destType = destType.getWidthlessType();
997 return destType.getConstType(
false) == srcType.getConstType(
false);
1002 bool srcOuterTypeIsConst) {
1004 if (destFType == srcFType)
1007 auto destType = type_dyn_cast<FIRRTLBaseType>(destFType);
1008 auto srcType = type_dyn_cast<FIRRTLBaseType>(srcFType);
1011 if (!destType || !srcType)
1015 if (!destType.isPassive() || !srcType.isPassive())
1018 bool srcIsConst = srcType.isConst() || srcOuterTypeIsConst;
1021 if (destType.isConst() && !srcIsConst)
1026 auto destVectorType = type_dyn_cast<FVectorType>(destType);
1027 auto srcVectorType = type_dyn_cast<FVectorType>(srcType);
1028 if (destVectorType && srcVectorType)
1029 return destVectorType.getNumElements() == srcVectorType.getNumElements() &&
1031 srcVectorType.getElementType(), srcIsConst);
1032 if (destVectorType != srcVectorType)
1037 auto destBundleType = type_dyn_cast<BundleType>(destType);
1038 auto srcBundleType = type_dyn_cast<BundleType>(srcType);
1039 if (destBundleType && srcBundleType) {
1040 auto destElements = destBundleType.getElements();
1041 auto srcElements = srcBundleType.getElements();
1042 size_t numDestElements = destElements.size();
1043 if (numDestElements != srcElements.size())
1046 return llvm::all_of_zip(
1047 destElements, srcElements,
1048 [&](
const auto &destElement,
const auto &srcElement) {
1049 return destElement.name == srcElement.name &&
1054 if (destBundleType != srcBundleType)
1059 return destType == srcType.getConstType(destType.isConst());
1063 auto dstRefType = type_dyn_cast<RefType>(dstType);
1064 auto srcRefType = type_dyn_cast<RefType>(srcType);
1065 if (!dstRefType || !srcRefType)
1067 if (dstRefType == srcRefType)
1069 if (dstRefType.getForceable() && !srcRefType.getForceable())
1081 bool srcOuterTypeIsConst) ->
bool {
1087 assert(dest.isPassive() && src.isPassive());
1089 bool srcIsConst = src.isConst() || srcOuterTypeIsConst;
1092 if (dest.isConst() && !srcIsConst)
1098 if (
auto destVectorType = type_dyn_cast<FVectorType>(dest)) {
1099 auto srcVectorType = type_dyn_cast<FVectorType>(src);
1100 return srcVectorType &&
1101 destVectorType.getNumElements() ==
1102 srcVectorType.getNumElements() &&
1103 f(f, destVectorType.getElementType(),
1104 srcVectorType.getElementType(), srcIsConst);
1107 if (
auto destBundleType = type_dyn_cast<BundleType>(dest)) {
1108 auto srcBundleType = type_dyn_cast<BundleType>(src);
1112 auto destElements = destBundleType.getElements();
1113 auto srcElements = srcBundleType.getElements();
1115 return destElements.size() == srcElements.size() &&
1117 destElements, srcElements,
1118 [&](
const auto &destElement,
const auto &srcElement) {
1119 return destElement.name == srcElement.name &&
1120 f(f, destElement.type, srcElement.type, srcIsConst);
1124 if (
auto destEnumType = type_dyn_cast<FEnumType>(dest)) {
1125 auto srcEnumType = type_dyn_cast<FEnumType>(src);
1128 auto destElements = destEnumType.getElements();
1129 auto srcElements = srcEnumType.getElements();
1131 return destElements.size() == srcElements.size() &&
1133 destElements, srcElements,
1134 [&](
const auto &destElement,
const auto &srcElement) {
1135 return destElement.name == srcElement.name &&
1136 f(f, destElement.type, srcElement.type, srcIsConst);
1141 if (type_isa<ResetType>(dest))
1142 return src.isResetType();
1146 src = src.getConstType(dest.isConst());
1149 if (dest.getBitWidthOrSentinel() == -1)
1150 src = src.getWidthlessType();
1155 return recurse(recurse, dstRefType.getType(), srcRefType.getType(),
false);
1162 return TypeSwitch<FIRRTLBaseType, bool>(dstType)
1163 .Case<BundleType>([&](
auto dstBundle) {
1164 auto srcBundle = type_cast<BundleType>(srcType);
1165 for (
size_t i = 0, n = dstBundle.getNumElements(); i < n; ++i) {
1166 auto srcElem = srcBundle.getElement(i);
1167 auto dstElem = dstBundle.getElement(i);
1168 if (dstElem.isFlip) {
1178 .Case<FVectorType>([&](
auto vector) {
1180 type_cast<FVectorType>(srcType).getElementType());
1182 .Default([&](
auto dstGround) {
1185 return destWidth <= -1 || srcWidth <= -1 || destWidth >= srcWidth;
1196 if (
auto destBaseType = type_dyn_cast<FIRRTLBaseType>(lhs))
1197 if (
auto srcBaseType = type_dyn_cast<FIRRTLBaseType>(rhs))
1200 if (
auto destRefType = type_dyn_cast<RefType>(lhs))
1201 if (
auto srcRefType = type_dyn_cast<RefType>(rhs))
1203 srcRefType.getType());
1211 return type_cast<FIRRTLBaseType>(anyBaseFIRRTLType).getPassiveType();
1215 return llvm::TypeSwitch<Type, bool>(type)
1217 return !type.containsReference() &&
1218 (!type.isPassive() || type.containsAnalog());
1230 int32_t widthOrSentinel,
bool isConst) {
1232 return SIntType::get(context, widthOrSentinel,
isConst);
1233 return UIntType::get(context, widthOrSentinel,
isConst);
1237 if (
auto sintType = type_dyn_cast<SIntType>(*
this))
1238 return sintType.getWidthOrSentinel();
1239 if (
auto uintType = type_dyn_cast<UIntType>(*
this))
1240 return uintType.getWidthOrSentinel();
1268 if (
auto sIntType = type_dyn_cast<SIntType>(*
this))
1277SIntType SIntType::get(MLIRContext *context) {
return get(context, -1,
false); }
1279SIntType SIntType::get(MLIRContext *context, std::optional<int32_t> width,
1281 return get(context, width ? *width : -1,
isConst);
1284LogicalResult SIntType::verify(function_ref<InFlightDiagnostic()> emitError,
1285 int32_t widthOrSentinel,
bool isConst) {
1286 if (widthOrSentinel < -1)
1287 return emitError() <<
"invalid width";
1291int32_t SIntType::getWidthOrSentinel()
const {
return getImpl()->width; }
1293SIntType SIntType::getConstType(
bool isConst) {
1296 return get(getContext(), getWidthOrSentinel(),
isConst);
1303UIntType UIntType::get(MLIRContext *context) {
return get(context, -1,
false); }
1305UIntType UIntType::get(MLIRContext *context, std::optional<int32_t> width,
1307 return get(context, width ? *width : -1,
isConst);
1310LogicalResult UIntType::verify(function_ref<InFlightDiagnostic()> emitError,
1311 int32_t widthOrSentinel,
bool isConst) {
1312 if (widthOrSentinel < -1)
1313 return emitError() <<
"invalid width";
1317int32_t UIntType::getWidthOrSentinel()
const {
return getImpl()->width; }
1319UIntType UIntType::getConstType(
bool isConst) {
1322 return get(getContext(), getWidthOrSentinel(),
isConst);
1331 using KeyTy = std::pair<ArrayRef<BundleType::BundleElement>,
char>;
1338 uint64_t fieldID = 0;
1341 auto type = element.type;
1342 auto eltInfo = type.getRecursiveTypeProperties();
1363 return llvm::hash_combine(
1364 llvm::hash_combine_range(key.first.begin(), key.first.end()),
1385BundleType BundleType::get(MLIRContext *context,
1386 ArrayRef<BundleElement> elements,
bool isConst) {
1387 return Base::get(context, elements,
isConst);
1390auto BundleType::getElements() const -> ArrayRef<BundleElement> {
1391 return getImpl()->elements;
1396 return getImpl()->props;
1401 auto *impl = getImpl();
1404 if (impl->passiveType)
1405 return impl->passiveType;
1408 if (impl->props.isPassive) {
1409 impl->passiveType = *
this;
1414 SmallVector<BundleType::BundleElement, 16> newElements;
1415 newElements.reserve(impl->elements.size());
1416 for (
auto &elt : impl->elements) {
1417 newElements.push_back({elt.name,
false, elt.type.getPassiveType()});
1420 auto passiveType = BundleType::get(getContext(), newElements,
isConst());
1421 impl->passiveType = passiveType;
1425BundleType BundleType::getConstType(
bool isConst) {
1428 return get(getContext(), getElements(),
isConst);
1431BundleType BundleType::getAllConstDroppedType() {
1435 SmallVector<BundleElement> constDroppedElements(
1436 llvm::map_range(getElements(), [](BundleElement element) {
1437 element.type = element.type.getAllConstDroppedType();
1440 return get(getContext(), constDroppedElements,
false);
1443std::optional<unsigned> BundleType::getElementIndex(StringAttr name) {
1444 for (
const auto &it :
llvm::enumerate(getElements())) {
1445 auto element = it.value();
1446 if (element.name == name) {
1447 return unsigned(it.index());
1450 return std::nullopt;
1453std::optional<unsigned> BundleType::getElementIndex(StringRef name) {
1454 for (
const auto &it :
llvm::enumerate(getElements())) {
1455 auto element = it.value();
1456 if (element.name.getValue() == name) {
1457 return unsigned(it.index());
1460 return std::nullopt;
1463StringAttr BundleType::getElementNameAttr(
size_t index) {
1464 assert(index < getNumElements() &&
1465 "index must be less than number of fields in bundle");
1466 return getElements()[index].name;
1469StringRef BundleType::getElementName(
size_t index) {
1470 return getElementNameAttr(index).getValue();
1473std::optional<BundleType::BundleElement>
1474BundleType::getElement(StringAttr name) {
1475 if (
auto maybeIndex = getElementIndex(name))
1476 return getElements()[*maybeIndex];
1477 return std::nullopt;
1480std::optional<BundleType::BundleElement>
1481BundleType::getElement(StringRef name) {
1482 if (
auto maybeIndex = getElementIndex(name))
1483 return getElements()[*maybeIndex];
1484 return std::nullopt;
1488BundleType::BundleElement BundleType::getElement(
size_t index) {
1489 assert(index < getNumElements() &&
1490 "index must be less than number of fields in bundle");
1491 return getElements()[index];
1495 auto element = getElement(name);
1500 auto element = getElement(name);
1505 assert(index < getNumElements() &&
1506 "index must be less than number of fields in bundle");
1507 return getElements()[index].type;
1510uint64_t BundleType::getFieldID(uint64_t index)
const {
1511 return getImpl()->fieldIDs[index];
1514uint64_t BundleType::getIndexForFieldID(uint64_t fieldID)
const {
1515 assert(!getElements().
empty() &&
"Bundle must have >0 fields");
1516 auto fieldIDs = getImpl()->fieldIDs;
1517 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
1518 return std::distance(fieldIDs.begin(), it);
1521std::pair<uint64_t, uint64_t>
1522BundleType::getIndexAndSubfieldID(uint64_t fieldID)
const {
1525 return {index, fieldID - elementFieldID};
1528std::pair<Type, uint64_t>
1529BundleType::getSubTypeByFieldID(uint64_t fieldID)
const {
1533 auto subfieldType = getElementType(subfieldIndex);
1534 auto subfieldID = fieldID -
getFieldID(subfieldIndex);
1535 return {subfieldType, subfieldID};
1538uint64_t BundleType::getMaxFieldID()
const {
return getImpl()->maxFieldID; }
1540std::pair<uint64_t, bool>
1541BundleType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
1543 auto rangeEnd = index + 1 >= getNumElements() ?
getMaxFieldID()
1545 return std::make_pair(fieldID - childRoot,
1546 fieldID >= childRoot && fieldID <= rangeEnd);
1549bool BundleType::isConst() {
return getImpl()->isConst; }
1551BundleType::ElementType
1552BundleType::getElementTypePreservingConst(
size_t index) {
1553 auto type = getElementType(index);
1554 return type.getConstType(type.isConst() ||
isConst());
1559 auto *impl = getImpl();
1562 if (impl->anonymousType)
1563 return impl->anonymousType;
1566 if (!impl->props.containsTypeAlias) {
1567 impl->anonymousType = *
this;
1573 SmallVector<BundleType::BundleElement, 16> newElements;
1574 newElements.reserve(impl->elements.size());
1575 for (
auto &elt : impl->elements)
1576 newElements.push_back({elt.name, elt.isFlip, elt.type.getAnonymousType()});
1578 auto anonymousType = BundleType::get(getContext(), newElements,
isConst());
1579 impl->anonymousType = anonymousType;
1580 return anonymousType;
1588 using KeyTy = std::pair<ArrayRef<OpenBundleType::BundleElement>,
char>;
1596 uint64_t fieldID = 0;
1599 auto type = element.type;
1600 auto eltInfo = type.getRecursiveTypeProperties();
1620 return llvm::hash_combine(
1621 llvm::hash_combine_range(key.first.begin(), key.first.end()),
1633 SmallVector<OpenBundleType::BundleElement, 4>
elements;
1645OpenBundleType OpenBundleType::get(MLIRContext *context,
1646 ArrayRef<BundleElement> elements,
1648 return Base::get(context, elements,
isConst);
1651auto OpenBundleType::getElements() const -> ArrayRef<BundleElement> {
1652 return getImpl()->elements;
1657 return getImpl()->props;
1660OpenBundleType OpenBundleType::getConstType(
bool isConst) {
1663 return get(getContext(), getElements(),
isConst);
1666std::optional<unsigned> OpenBundleType::getElementIndex(StringAttr name) {
1667 for (
const auto &it :
llvm::enumerate(getElements())) {
1668 auto element = it.value();
1669 if (element.name == name) {
1670 return unsigned(it.index());
1673 return std::nullopt;
1676std::optional<unsigned> OpenBundleType::getElementIndex(StringRef name) {
1677 for (
const auto &it :
llvm::enumerate(getElements())) {
1678 auto element = it.value();
1679 if (element.name.getValue() == name) {
1680 return unsigned(it.index());
1683 return std::nullopt;
1686StringAttr OpenBundleType::getElementNameAttr(
size_t index) {
1687 assert(index < getNumElements() &&
1688 "index must be less than number of fields in bundle");
1689 return getElements()[index].name;
1692StringRef OpenBundleType::getElementName(
size_t index) {
1693 return getElementNameAttr(index).getValue();
1696std::optional<OpenBundleType::BundleElement>
1697OpenBundleType::getElement(StringAttr name) {
1698 if (
auto maybeIndex = getElementIndex(name))
1699 return getElements()[*maybeIndex];
1700 return std::nullopt;
1703std::optional<OpenBundleType::BundleElement>
1704OpenBundleType::getElement(StringRef name) {
1705 if (
auto maybeIndex = getElementIndex(name))
1706 return getElements()[*maybeIndex];
1707 return std::nullopt;
1711OpenBundleType::BundleElement OpenBundleType::getElement(
size_t index) {
1712 assert(index < getNumElements() &&
1713 "index must be less than number of fields in bundle");
1714 return getElements()[index];
1717OpenBundleType::ElementType OpenBundleType::getElementType(StringAttr name) {
1718 auto element = getElement(name);
1722OpenBundleType::ElementType OpenBundleType::getElementType(StringRef name) {
1723 auto element = getElement(name);
1727OpenBundleType::ElementType OpenBundleType::getElementType(
size_t index)
const {
1728 assert(index < getNumElements() &&
1729 "index must be less than number of fields in bundle");
1730 return getElements()[index].type;
1733uint64_t OpenBundleType::getFieldID(uint64_t index)
const {
1734 return getImpl()->fieldIDs[index];
1737uint64_t OpenBundleType::getIndexForFieldID(uint64_t fieldID)
const {
1738 assert(!getElements().
empty() &&
"Bundle must have >0 fields");
1739 auto fieldIDs = getImpl()->fieldIDs;
1740 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
1741 return std::distance(fieldIDs.begin(), it);
1744std::pair<uint64_t, uint64_t>
1745OpenBundleType::getIndexAndSubfieldID(uint64_t fieldID)
const {
1748 return {index, fieldID - elementFieldID};
1751std::pair<Type, uint64_t>
1752OpenBundleType::getSubTypeByFieldID(uint64_t fieldID)
const {
1756 auto subfieldType = getElementType(subfieldIndex);
1757 auto subfieldID = fieldID -
getFieldID(subfieldIndex);
1758 return {subfieldType, subfieldID};
1761uint64_t OpenBundleType::getMaxFieldID()
const {
return getImpl()->maxFieldID; }
1763std::pair<uint64_t, bool>
1764OpenBundleType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
1766 auto rangeEnd = index + 1 >= getNumElements() ?
getMaxFieldID()
1768 return std::make_pair(fieldID - childRoot,
1769 fieldID >= childRoot && fieldID <= rangeEnd);
1772bool OpenBundleType::isConst() {
return getImpl()->isConst; }
1774OpenBundleType::ElementType
1775OpenBundleType::getElementTypePreservingConst(
size_t index) {
1776 auto type = getElementType(index);
1778 return TypeSwitch<FIRRTLType, ElementType>(type)
1779 .Case<
FIRRTLBaseType, OpenBundleType, OpenVectorType>([&](
auto type) {
1780 return type.getConstType(type.isConst() ||
isConst());
1786OpenBundleType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
1787 ArrayRef<BundleElement> elements,
bool isConst) {
1788 for (
auto &element : elements) {
1790 return emitErrorFn()
1791 <<
"'const' bundle cannot have references, but element "
1792 << element.name <<
" has type " << element.type;
1793 if (type_isa<LHSType>(element.type))
1794 return emitErrorFn() <<
"bundle element " << element.name
1795 <<
" cannot have a left-hand side type";
1807 using KeyTy = std::tuple<FIRRTLBaseType, size_t, char>;
1825 static_cast<bool>(std::get<2>(key)));
1844 return getImpl()->elementType;
1847size_t FVectorType::getNumElements()
const {
return getImpl()->numElements; }
1851 return getImpl()->props;
1856 auto *impl = getImpl();
1859 if (impl->passiveType)
1860 return impl->passiveType;
1863 if (impl->elementType.getRecursiveTypeProperties().isPassive)
1864 return impl->passiveType = *
this;
1867 auto passiveType = FVectorType::get(getElementType().
getPassiveType(),
1869 impl->passiveType = passiveType;
1873FVectorType FVectorType::getConstType(
bool isConst) {
1876 return get(getElementType(), getNumElements(),
isConst);
1879FVectorType FVectorType::getAllConstDroppedType() {
1882 return get(getElementType().getAllConstDroppedType(), getNumElements(),
1888 auto *impl = getImpl();
1890 if (impl->anonymousType)
1891 return impl->anonymousType;
1894 if (!impl->props.containsTypeAlias)
1895 return impl->anonymousType = *
this;
1898 auto anonymousType = FVectorType::get(getElementType().getAnonymousType(),
1900 impl->anonymousType = anonymousType;
1901 return anonymousType;
1904uint64_t FVectorType::getFieldID(uint64_t index)
const {
1908uint64_t FVectorType::getIndexForFieldID(uint64_t fieldID)
const {
1909 assert(fieldID &&
"fieldID must be at least 1");
1914std::pair<uint64_t, uint64_t>
1915FVectorType::getIndexAndSubfieldID(uint64_t fieldID)
const {
1918 return {index, fieldID - elementFieldID};
1921std::pair<Type, uint64_t>
1922FVectorType::getSubTypeByFieldID(uint64_t fieldID)
const {
1928uint64_t FVectorType::getMaxFieldID()
const {
1929 return getNumElements() *
1933std::pair<uint64_t, bool>
1934FVectorType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
1938 return std::make_pair(fieldID - childRoot,
1939 fieldID >= childRoot && fieldID <= rangeEnd);
1942bool FVectorType::isConst() {
return getImpl()->isConst; }
1944FVectorType::ElementType FVectorType::getElementTypePreservingConst() {
1945 auto type = getElementType();
1946 return type.getConstType(type.isConst() ||
isConst());
1954 using KeyTy = std::tuple<FIRRTLType, size_t, char>;
1972 static_cast<bool>(std::get<2>(key)));
1987FIRRTLType OpenVectorType::getElementType()
const {
1988 return getImpl()->elementType;
1991size_t OpenVectorType::getNumElements()
const {
return getImpl()->numElements; }
1995 return getImpl()->props;
1998OpenVectorType OpenVectorType::getConstType(
bool isConst) {
2001 return get(getElementType(), getNumElements(),
isConst);
2004uint64_t OpenVectorType::getFieldID(uint64_t index)
const {
2008uint64_t OpenVectorType::getIndexForFieldID(uint64_t fieldID)
const {
2009 assert(fieldID &&
"fieldID must be at least 1");
2014std::pair<uint64_t, uint64_t>
2015OpenVectorType::getIndexAndSubfieldID(uint64_t fieldID)
const {
2018 return {index, fieldID - elementFieldID};
2021std::pair<Type, uint64_t>
2022OpenVectorType::getSubTypeByFieldID(uint64_t fieldID)
const {
2028uint64_t OpenVectorType::getMaxFieldID()
const {
2030 return getNumElements() *
2034std::pair<uint64_t, bool>
2035OpenVectorType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
2039 return std::make_pair(fieldID - childRoot,
2040 fieldID >= childRoot && fieldID <= rangeEnd);
2043bool OpenVectorType::isConst() {
return getImpl()->isConst; }
2045OpenVectorType::ElementType OpenVectorType::getElementTypePreservingConst() {
2046 auto type = getElementType();
2048 return TypeSwitch<FIRRTLType, ElementType>(type)
2049 .Case<
FIRRTLBaseType, OpenBundleType, OpenVectorType>([&](
auto type) {
2050 return type.getConstType(type.isConst() ||
isConst());
2056OpenVectorType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
2060 return emitErrorFn() <<
"vector cannot be const with references";
2062 return emitErrorFn() <<
"vector cannot have a left-hand side type";
2071 using KeyTy = std::pair<ArrayRef<FEnumType::EnumElement>,
char>;
2077 false,
false,
false};
2078 uint64_t fieldID = 0;
2081 auto type = element.type;
2082 auto eltInfo = type.getRecursiveTypeProperties();
2084 props.containsAnalog |= eltInfo.containsAnalog;
2085 props.containsConst |= eltInfo.containsConst;
2086 props.containsReference |= eltInfo.containsReference;
2087 props.containsTypeAlias |= eltInfo.containsTypeAlias;
2088 props.hasUninferredReset |= eltInfo.hasUninferredReset;
2089 props.hasUninferredWidth |= eltInfo.hasUninferredWidth;
2104 return llvm::hash_combine(
2105 llvm::hash_combine_range(key.first.begin(), key.first.end()),
2123FEnumType FEnumType::get(::mlir::MLIRContext *context,
2124 ArrayRef<EnumElement> elements,
bool isConst) {
2125 return Base::get(context, elements,
isConst);
2128ArrayRef<FEnumType::EnumElement> FEnumType::getElements()
const {
2129 return getImpl()->elements;
2132FEnumType FEnumType::getConstType(
bool isConst) {
2133 return get(getContext(), getElements(),
isConst);
2136FEnumType FEnumType::getAllConstDroppedType() {
2140 SmallVector<EnumElement> constDroppedElements(
2141 llvm::map_range(getElements(), [](EnumElement element) {
2142 element.type = element.type.getAllConstDroppedType();
2145 return get(getContext(), constDroppedElements,
false);
2150 return getImpl()->recProps;
2153std::optional<unsigned> FEnumType::getElementIndex(StringAttr name) {
2154 for (
const auto &it :
llvm::enumerate(getElements())) {
2155 auto element = it.value();
2156 if (element.name == name) {
2157 return unsigned(it.index());
2160 return std::nullopt;
2163std::optional<unsigned> FEnumType::getElementIndex(StringRef name) {
2164 for (
const auto &it :
llvm::enumerate(getElements())) {
2165 auto element = it.value();
2166 if (element.name.getValue() == name) {
2167 return unsigned(it.index());
2170 return std::nullopt;
2173StringAttr FEnumType::getElementNameAttr(
size_t index) {
2174 assert(index < getNumElements() &&
2175 "index must be less than number of fields in enum");
2176 return getElements()[index].name;
2179StringRef FEnumType::getElementName(
size_t index) {
2180 return getElementNameAttr(index).getValue();
2183std::optional<FEnumType::EnumElement> FEnumType::getElement(StringAttr name) {
2184 if (
auto maybeIndex = getElementIndex(name))
2185 return getElements()[*maybeIndex];
2186 return std::nullopt;
2189std::optional<FEnumType::EnumElement> FEnumType::getElement(StringRef name) {
2190 if (
auto maybeIndex = getElementIndex(name))
2191 return getElements()[*maybeIndex];
2192 return std::nullopt;
2196FEnumType::EnumElement FEnumType::getElement(
size_t index) {
2197 assert(index < getNumElements() &&
2198 "index must be less than number of fields in enum");
2199 return getElements()[index];
2203 auto element = getElement(name);
2208 auto element = getElement(name);
2213 assert(index < getNumElements() &&
2214 "index must be less than number of fields in enum");
2215 return getElements()[index].type;
2218FIRRTLBaseType FEnumType::getElementTypePreservingConst(
size_t index) {
2219 auto type = getElementType(index);
2220 return type.getConstType(type.isConst() ||
isConst());
2223uint64_t FEnumType::getFieldID(uint64_t index)
const {
2224 return getImpl()->fieldIDs[index];
2227uint64_t FEnumType::getIndexForFieldID(uint64_t fieldID)
const {
2228 assert(!getElements().
empty() &&
"Enum must have >0 fields");
2229 auto fieldIDs = getImpl()->fieldIDs;
2230 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
2231 return std::distance(fieldIDs.begin(), it);
2234std::pair<uint64_t, uint64_t>
2235FEnumType::getIndexAndSubfieldID(uint64_t fieldID)
const {
2238 return {index, fieldID - elementFieldID};
2241std::pair<Type, uint64_t>
2242FEnumType::getSubTypeByFieldID(uint64_t fieldID)
const {
2246 auto subfieldType = getElementType(subfieldIndex);
2247 auto subfieldID = fieldID -
getFieldID(subfieldIndex);
2248 return {subfieldType, subfieldID};
2251uint64_t FEnumType::getMaxFieldID()
const {
return getImpl()->maxFieldID; }
2253std::pair<uint64_t, bool>
2254FEnumType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
2256 auto rangeEnd = index + 1 >= getNumElements() ?
getMaxFieldID()
2258 return std::make_pair(fieldID - childRoot,
2259 fieldID >= childRoot && fieldID <= rangeEnd);
2262auto FEnumType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
2263 ArrayRef<EnumElement> elements,
bool isConst)
2265 for (
auto &elt : elements) {
2266 auto r = elt.type.getRecursiveTypeProperties();
2268 return emitErrorFn() <<
"enum field '" << elt.name <<
"' not passive";
2269 if (r.containsAnalog)
2270 return emitErrorFn() <<
"enum field '" << elt.name <<
"' contains analog";
2271 if (r.containsConst && !
isConst)
2272 return emitErrorFn() <<
"enum with 'const' elements must be 'const'";
2280 auto *impl = getImpl();
2282 if (impl->anonymousType)
2283 return impl->anonymousType;
2285 if (!impl->recProps.containsTypeAlias)
2286 return impl->anonymousType = *
this;
2288 SmallVector<FEnumType::EnumElement, 4> elements;
2290 for (
auto element : getElements())
2291 elements.push_back({element.name, element.type.getAnonymousType()});
2292 return impl->anonymousType = FEnumType::get(getContext(), elements);
2301 using KeyTy = std::tuple<StringAttr, FIRRTLBaseType>;
2312 return llvm::hash_combine(key);
2325auto BaseTypeAliasType::get(StringAttr name,
FIRRTLBaseType innerType)
2326 -> BaseTypeAliasType {
2327 return Base::get(name.getContext(), name, innerType);
2330auto BaseTypeAliasType::getName() const -> StringAttr {
2331 return getImpl()->name;
2335 return getImpl()->innerType;
2339 auto *impl = getImpl();
2340 if (impl->anonymousType)
2341 return impl->anonymousType;
2342 return impl->anonymousType = getInnerType().getAnonymousType();
2350 auto rtp = getInnerType().getRecursiveTypeProperties();
2358 if (newInnerType == getInnerType())
2360 return newInnerType;
2365 return getModifiedType(getInnerType().getAllConstDroppedType());
2369 return getModifiedType(getInnerType().getConstType(
isConst));
2372std::pair<Type, uint64_t>
2373BaseTypeAliasType::getSubTypeByFieldID(uint64_t fieldID)
const {
2377uint64_t BaseTypeAliasType::getMaxFieldID()
const {
2381std::pair<uint64_t, bool>
2382BaseTypeAliasType::projectToChildFieldID(uint64_t fieldID,
2383 uint64_t index)
const {
2387uint64_t BaseTypeAliasType::getIndexForFieldID(uint64_t fieldID)
const {
2391uint64_t BaseTypeAliasType::getFieldID(uint64_t index)
const {
2395std::pair<uint64_t, uint64_t>
2396BaseTypeAliasType::getIndexAndSubfieldID(uint64_t fieldID)
const {
2405 return LHSType::get(type.getContext(), type);
2408LogicalResult LHSType::verify(function_ref<InFlightDiagnostic()> emitError,
2410 if (type.containsAnalog())
2411 return emitError() <<
"lhs type cannot contain an AnalogType";
2413 return emitError() <<
"lhs type cannot contain a non-passive type";
2414 if (type.containsReference())
2415 return emitError() <<
"lhs type cannot contain a reference";
2416 if (type_isa<LHSType>(type))
2417 return emitError() <<
"lhs type cannot contain a lhs type";
2426auto RefType::get(
FIRRTLBaseType type,
bool forceable, SymbolRefAttr layer)
2428 return Base::get(type.getContext(), type, forceable, layer);
2431auto RefType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
2434 if (!base.isPassive())
2435 return emitErrorFn() <<
"reference base type must be passive";
2436 if (forceable && base.containsConst())
2437 return emitErrorFn()
2438 <<
"forceable reference base type cannot contain const";
2443 auto rtp = getType().getRecursiveTypeProperties();
2446 rtp.isPassive =
false;
2454AnalogType AnalogType::get(mlir::MLIRContext *context) {
2455 return AnalogType::get(context, -1,
false);
2458AnalogType AnalogType::get(mlir::MLIRContext *context,
2459 std::optional<int32_t> width,
bool isConst) {
2460 return AnalogType::get(context, width ? *width : -1,
isConst);
2463LogicalResult AnalogType::verify(function_ref<InFlightDiagnostic()> emitError,
2464 int32_t widthOrSentinel,
bool isConst) {
2465 if (widthOrSentinel < -1)
2466 return emitError() <<
"invalid width";
2470int32_t AnalogType::getWidthOrSentinel()
const {
return getImpl()->width; }
2472AnalogType AnalogType::getConstType(
bool isConst) {
2475 return get(getContext(), getWidthOrSentinel(),
isConst);
2482ClockType ClockType::getConstType(
bool isConst) {
2492ResetType ResetType::getConstType(
bool isConst) {
2502AsyncResetType AsyncResetType::getConstType(
bool isConst) {
2513 using KeyTy = std::pair<FlatSymbolRefAttr, ArrayRef<ClassElement>>;
2517 auto name = key.first;
2518 auto elements = allocator.copyInto(key.second);
2521 SmallVector<uint64_t, 4> ids;
2530 auto fieldIDs = allocator.copyInto(ArrayRef(ids));
2552ClassType ClassType::get(FlatSymbolRefAttr name,
2553 ArrayRef<ClassElement> elements) {
2554 return get(name.getContext(), name, elements);
2557StringRef ClassType::getName()
const {
2558 return getNameAttr().getAttr().getValue();
2561FlatSymbolRefAttr ClassType::getNameAttr()
const {
return getImpl()->name; }
2563ArrayRef<ClassElement> ClassType::getElements()
const {
2564 return getImpl()->elements;
2567const ClassElement &ClassType::getElement(IntegerAttr index)
const {
2568 return getElement(index.getValue().getZExtValue());
2571const ClassElement &ClassType::getElement(
size_t index)
const {
2572 return getElements()[index];
2575std::optional<uint64_t> ClassType::getElementIndex(StringRef fieldName)
const {
2576 for (
const auto [i, e] :
llvm::enumerate(getElements()))
2577 if (fieldName == e.name)
2582void ClassType::printInterface(AsmPrinter &p)
const {
2586 for (
const auto &element : getElements()) {
2590 p.printKeywordOrString(element.name);
2591 p <<
": " << element.type;
2597uint64_t ClassType::getFieldID(uint64_t index)
const {
2598 return getImpl()->fieldIDs[index];
2601uint64_t ClassType::getIndexForFieldID(uint64_t fieldID)
const {
2602 assert(!getElements().
empty() &&
"Class must have >0 fields");
2603 auto fieldIDs = getImpl()->fieldIDs;
2604 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
2605 return std::distance(fieldIDs.begin(), it);
2608std::pair<uint64_t, uint64_t>
2609ClassType::getIndexAndSubfieldID(uint64_t fieldID)
const {
2612 return {index, fieldID - elementFieldID};
2615std::pair<Type, uint64_t>
2616ClassType::getSubTypeByFieldID(uint64_t fieldID)
const {
2620 auto subfieldType = getElement(subfieldIndex).type;
2621 auto subfieldID = fieldID -
getFieldID(subfieldIndex);
2622 return {subfieldType, subfieldID};
2625uint64_t ClassType::getMaxFieldID()
const {
return getImpl()->maxFieldID; }
2627std::pair<uint64_t, bool>
2628ClassType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
2630 auto rangeEnd = index + 1 >= getNumElements() ?
getMaxFieldID()
2632 return std::make_pair(fieldID - childRoot,
2633 fieldID >= childRoot && fieldID <= rangeEnd);
2636ParseResult ClassType::parseInterface(AsmParser &parser, ClassType &result) {
2637 StringAttr className;
2638 if (parser.parseSymbolName(className))
2641 SmallVector<ClassElement> elements;
2642 if (parser.parseCommaSeparatedList(
2643 OpAsmParser::Delimiter::Paren, [&]() -> ParseResult {
2645 Direction direction;
2646 if (succeeded(parser.parseOptionalKeyword(
"out")))
2647 direction = Direction::Out;
2648 else if (succeeded(parser.parseKeyword(
"in",
"or 'out'")))
2649 direction = Direction::In;
2654 std::string keyword;
2655 if (parser.parseKeywordOrString(&keyword))
2657 StringAttr name = StringAttr::get(parser.getContext(), keyword);
2661 if (parser.parseColonType(type))
2664 elements.emplace_back(name, type, direction);
2669 result = ClassType::get(FlatSymbolRefAttr::get(className), elements);
2677void FIRRTLDialect::registerTypes() {
2679#define GET_TYPEDEF_LIST
2680#include "circt/Dialect/FIRRTL/FIRRTLTypes.cpp.inc"
2694 return TypeSwitch<FIRRTLBaseType, std::optional<int64_t>>(type)
2695 .Case<BundleType>([&](BundleType bundle) -> std::optional<int64_t> {
2697 for (
auto &elt : bundle) {
2698 if (elt.isFlip && !ignoreFlip)
2699 return std::nullopt;
2702 return std::nullopt;
2707 .Case<FEnumType>([&](FEnumType fenum) -> std::optional<int64_t> {
2709 for (
auto &elt : fenum) {
2712 return std::nullopt;
2713 width = std::max(width, *w);
2715 return width + llvm::Log2_32_Ceil(fenum.getNumElements());
2717 .Case<FVectorType>([&](
auto vector) -> std::optional<int64_t> {
2720 return std::nullopt;
2721 return *w * vector.getNumElements();
2724 .Case<ClockType, ResetType, AsyncResetType>([](Type) {
return 1; })
2725 .Default([&](
auto t) {
return std::nullopt; });
2727 return getWidth(type);
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 getFieldID(BundleType type, unsigned index)
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.
bool isPassive() const
Return true if this is a "passive" type - one that contains no "flip" types recursively within itself...
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.
This class implements the same functionality as TypeSwitch except that it uses firrtl::type_dyn_cast ...
FIRRTLTypeSwitch< T, ResultT > & Case(CallableT &&caseFn)
Add a case on the given type.
bool containsReference()
Return true if this is or contains a Reference 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.
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.
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 ...
bool hasZeroBitWidth(FIRRTLType type)
Return true if the type has zero bit width.
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.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
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
static BundleTypeStorage * construct(TypeStorageAllocator &allocator, KeyTy key)
SmallVector< BundleType::BundleElement, 4 > elements
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
ArrayRef< uint64_t > fieldIDs
static ClassTypeStorage * construct(TypeStorageAllocator &allocator, KeyTy key)
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
static FEnumTypeStorage * construct(TypeStorageAllocator &allocator, KeyTy key)
FEnumTypeStorage(ArrayRef< FEnumType::EnumElement > elements, bool isConst)
std::pair< ArrayRef< FEnumType::EnumElement >, char > KeyTy
RecursiveTypeProperties recProps
FIRRTLBaseType anonymousType
SmallVector< uint64_t, 4 > fieldIDs
bool operator==(const KeyTy &key) const
FIRRTLBaseTypeStorage(bool isConst)
static FIRRTLBaseTypeStorage * construct(TypeStorageAllocator &allocator, KeyTy key)
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
static FVectorTypeStorage * construct(TypeStorageAllocator &allocator, KeyTy key)
FIRRTLBaseType anonymousType
std::tuple< FIRRTLBaseType, size_t, char > KeyTy
FVectorTypeStorage(FIRRTLBaseType elementType, size_t numElements, bool isConst)
SmallVector< OpenBundleType::BundleElement, 4 > elements
bool operator==(const KeyTy &key) const
static OpenBundleTypeStorage * construct(TypeStorageAllocator &allocator, KeyTy key)
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
static OpenVectorTypeStorage * construct(TypeStorageAllocator &allocator, KeyTy key)
OpenVectorTypeStorage(FIRRTLType elementType, size_t numElements, bool isConst)
WidthTypeStorage(int32_t width, bool isConst)
bool operator==(const KeyTy &key) const
std::pair< int32_t, char > KeyTy
static WidthTypeStorage * construct(TypeStorageAllocator &allocator, const KeyTy &key)