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 .Default([&](
auto) { anyFailed =
true; });
143 return failure(anyFailed);
154 assert(
false &&
"type to print unknown to FIRRTL dialect");
189 const char constPrefix[] =
"const.";
190 if (name.starts_with(constPrefix)) {
192 name = name.drop_front(std::size(constPrefix) - 1);
195 auto *context = parser.getContext();
197 return result = ClockType::get(context,
isConst), success();
199 return result = ResetType::get(context,
isConst), success();
200 if (name ==
"asyncreset")
201 return result = AsyncResetType::get(context,
isConst), success();
203 if (name ==
"sint" || name ==
"uint" || name ==
"analog") {
206 if (!parser.parseOptionalLess()) {
207 if (parser.parseInteger(width) || parser.parseGreater())
211 return parser.emitError(parser.getNameLoc(),
"unknown width"),
216 result = SIntType::get(context, width,
isConst);
217 else if (name ==
"uint")
218 result = UIntType::get(context, width,
isConst);
221 result = AnalogType::get(context, width,
isConst);
226 if (name ==
"bundle") {
227 SmallVector<BundleType::BundleElement, 4> elements;
229 auto parseBundleElement = [&]() -> ParseResult {
234 if (failed(parser.parseKeywordOrString(&nameStr)))
238 bool isFlip = succeeded(parser.parseOptionalKeyword(
"flip"));
242 elements.push_back({StringAttr::get(context, name), isFlip, type});
246 if (parser.parseCommaSeparatedList(mlir::AsmParser::Delimiter::LessGreater,
250 return result = BundleType::get(context, elements,
isConst), success();
252 if (name ==
"openbundle") {
253 SmallVector<OpenBundleType::BundleElement, 4> elements;
255 auto parseBundleElement = [&]() -> ParseResult {
260 if (failed(parser.parseKeywordOrString(&nameStr)))
264 bool isFlip = succeeded(parser.parseOptionalKeyword(
"flip"));
268 elements.push_back({StringAttr::get(context, name), isFlip, type});
272 if (parser.parseCommaSeparatedList(mlir::AsmParser::Delimiter::LessGreater,
276 result = parser.getChecked<OpenBundleType>(context, elements,
isConst);
277 return failure(!result);
280 if (name ==
"enum") {
281 SmallVector<FEnumType::EnumElement, 4> elements;
283 auto parseEnumElement = [&]() -> ParseResult {
288 if (failed(parser.parseKeywordOrString(&nameStr)))
295 elements.push_back({StringAttr::get(context, name), type});
299 if (parser.parseCommaSeparatedList(mlir::AsmParser::Delimiter::LessGreater,
302 if (failed(FEnumType::verify(
303 [&]() {
return parser.emitError(parser.getNameLoc()); }, elements,
307 return result = FEnumType::get(context, elements,
isConst), success();
310 if (name ==
"vector") {
315 parser.parseComma() || parser.parseInteger(width) ||
316 parser.parseGreater())
321 if (name ==
"openvector") {
326 parser.parseComma() || parser.parseInteger(width) ||
327 parser.parseGreater())
332 return failure(!result);
336 if (name ==
"ref" || name ==
"probe") {
343 if (parser.parseOptionalComma().succeeded())
344 if (parser.parseOptionalAttribute(layer).value())
345 return parser.emitError(parser.getNameLoc(),
346 "expected symbol reference");
347 if (parser.parseGreater())
350 if (failed(RefType::verify(
351 [&]() {
return parser.emitError(parser.getNameLoc()); }, type,
355 return result = RefType::get(type,
false, layer), success();
360 parser.parseGreater())
362 if (!isa<FIRRTLBaseType>(type))
363 return parser.emitError(parser.getNameLoc(),
"expected base type");
364 result = parser.getChecked<LHSType>(context, cast<FIRRTLBaseType>(type));
365 return failure(!result);
367 if (name ==
"rwprobe") {
372 if (parser.parseOptionalComma().succeeded())
373 if (parser.parseOptionalAttribute(layer).value())
374 return parser.emitError(parser.getNameLoc(),
375 "expected symbol reference");
376 if (parser.parseGreater())
379 if (failed(RefType::verify(
380 [&]() {
return parser.emitError(parser.getNameLoc()); }, type,
true,
384 return result = RefType::get(type,
true, layer), success();
386 if (name ==
"class") {
388 return parser.emitError(parser.getNameLoc(),
"classes cannot be const");
390 if (parser.parseLess() || ClassType::parseInterface(parser, classType) ||
391 parser.parseGreater())
396 if (name ==
"anyref") {
398 return parser.emitError(parser.getNameLoc(),
"any refs cannot be const");
400 result = AnyRefType::get(parser.getContext());
403 if (name ==
"string") {
405 parser.emitError(parser.getNameLoc(),
"strings cannot be const");
408 result = StringType::get(parser.getContext());
411 if (name ==
"integer") {
413 parser.emitError(parser.getNameLoc(),
"bigints cannot be const");
416 result = FIntegerType::get(parser.getContext());
419 if (name ==
"bool") {
421 parser.emitError(parser.getNameLoc(),
"bools cannot be const");
424 result = BoolType::get(parser.getContext());
427 if (name ==
"double") {
429 parser.emitError(parser.getNameLoc(),
"doubles cannot be const");
432 result = DoubleType::get(parser.getContext());
435 if (name ==
"list") {
437 parser.emitError(parser.getNameLoc(),
"lists cannot be const");
442 parser.parseGreater())
444 result = parser.getChecked<ListType>(context,
elementType);
449 if (name ==
"path") {
451 parser.emitError(parser.getNameLoc(),
"path cannot be const");
454 result = PathType::get(parser.getContext());
457 if (name ==
"alias") {
460 if (parser.parseLess() || parser.parseKeyword(&name) ||
462 parser.parseGreater())
466 BaseTypeAliasType::get(StringAttr::get(context, name), type),
478static ParseResult
parseType(Type &result, StringRef name, AsmParser &parser) {
481 if (parseResult.has_value())
482 return parseResult.value();
485 parser.emitError(parser.getNameLoc(),
"unknown FIRRTL dialect type: \"")
497 if (failed(
parseType(type, name, parser)))
499 result = type_dyn_cast<FIRRTLType>(type);
502 parser.emitError(parser.getNameLoc(),
"unknown FIRRTL type: \"")
512 if (
auto base = type_dyn_cast<FIRRTLBaseType>(type)) {
516 parser.emitError(parser.getNameLoc(),
"expected base type, found ") << type;
525 if (
auto prop = type_dyn_cast<PropertyType>(type)) {
529 parser.emitError(parser.getNameLoc(),
"expected property type, found ")
542 if (parser.parseKeyword(&name))
552 if (parser.parseKeyword(&name))
562 if (parser.parseKeyword(&name))
573void FIRRTLDialect::printType(Type type, DialectAsmPrinter &os)
const {
578Type FIRRTLDialect::parseType(DialectAsmParser &parser)
const {
581 if (parser.parseKeyword(&name) ||
::parseType(result, name, parser))
624bool FIRRTLType::isGround() {
625 return TypeSwitch<FIRRTLType, bool>(*
this)
626 .Case<ClockType, ResetType, AsyncResetType, SIntType, UIntType,
627 AnalogType>([](Type) {
return true; })
628 .Case<BundleType, FVectorType, FEnumType, OpenBundleType, OpenVectorType>(
629 [](Type) {
return false; })
630 .Case<BaseTypeAliasType>([](BaseTypeAliasType alias) {
631 return alias.getAnonymousType().isGround();
634 .Case<PropertyType, RefType>([](Type) {
return false; })
636 llvm_unreachable(
"unknown FIRRTL type");
642 return TypeSwitch<FIRRTLType, bool>(*
this)
644 [](
auto type) {
return type.isConst(); })
651 return TypeSwitch<FIRRTLType, RecursiveTypeProperties>(*
this)
652 .Case<ClockType, ResetType, AsyncResetType>([](
FIRRTLBaseType type) {
659 firrtl::type_isa<ResetType>(type)};
661 .Case<SIntType, UIntType>([](
auto type) {
663 true,
false,
false, type.isConst(),
false, !type.hasWidth(),
false};
665 .Case<AnalogType>([](
auto type) {
667 true,
false,
true, type.isConst(),
false, !type.hasWidth(),
false};
669 .Case<BundleType, FVectorType, FEnumType, OpenBundleType, OpenVectorType,
670 RefType, BaseTypeAliasType>(
671 [](
auto type) {
return type.getRecursiveTypeProperties(); })
672 .Case<PropertyType>([](
auto type) {
674 false,
false,
false};
677 [](
auto type) {
return type.getType().getRecursiveTypeProperties(); })
679 llvm_unreachable(
"unknown FIRRTL type");
686 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
687 .Case<ClockType, ResetType, AsyncResetType, SIntType, UIntType,
688 AnalogType>([&](Type) {
return *
this; })
689 .Case<BundleType, FVectorType, FEnumType, BaseTypeAliasType>(
690 [](
auto type) {
return type.getAnonymousType(); })
692 llvm_unreachable(
"unknown FIRRTL type");
699 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
700 .Case<ClockType, ResetType, AsyncResetType, SIntType, UIntType,
701 AnalogType, FEnumType>([&](Type) {
return *
this; })
702 .Case<BundleType, FVectorType, FEnumType, BaseTypeAliasType>(
703 [](
auto type) {
return type.getPassiveType(); })
705 llvm_unreachable(
"unknown FIRRTL type");
712 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
713 .Case<ClockType, ResetType, AsyncResetType, AnalogType, SIntType,
714 UIntType, BundleType, FVectorType, FEnumType, BaseTypeAliasType>(
715 [&](
auto type) {
return type.getConstType(
isConst); })
717 llvm_unreachable(
"unknown FIRRTL type");
724 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
725 .Case<ClockType, ResetType, AsyncResetType, AnalogType, SIntType,
726 UIntType>([&](
auto type) {
return type.getConstType(
false); })
727 .Case<BundleType, FVectorType, FEnumType, BaseTypeAliasType>(
728 [&](
auto type) {
return type.getAllConstDroppedType(); })
730 llvm_unreachable(
"unknown FIRRTL type");
738 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
739 .Case<ClockType, ResetType, AsyncResetType, SIntType, UIntType,
740 AnalogType>([&](Type) {
741 return UIntType::get(this->getContext(), 1, this->
isConst());
743 .Case<BundleType>([&](BundleType bundleType) {
744 SmallVector<BundleType::BundleElement, 4> newElements;
745 newElements.reserve(bundleType.getElements().size());
746 for (
auto elt : bundleType)
747 newElements.push_back(
748 {elt.name,
false , elt.type.getMaskType()});
749 return BundleType::get(this->getContext(), newElements,
750 bundleType.isConst());
752 .Case<FVectorType>([](FVectorType vectorType) {
753 return FVectorType::get(vectorType.getElementType().getMaskType(),
754 vectorType.getNumElements(),
755 vectorType.isConst());
757 .Case<BaseTypeAliasType>([](BaseTypeAliasType base) {
758 return base.getModifiedType(base.getInnerType().getMaskType());
761 llvm_unreachable(
"unknown FIRRTL type");
769 return TypeSwitch<FIRRTLBaseType, FIRRTLBaseType>(*
this)
770 .Case<ClockType, ResetType, AsyncResetType>([](
auto a) {
return a; })
771 .Case<UIntType, SIntType, AnalogType>(
772 [&](
auto a) {
return a.get(this->getContext(), -1, a.isConst()); })
773 .Case<BundleType>([&](
auto a) {
774 SmallVector<BundleType::BundleElement, 4> newElements;
775 newElements.reserve(a.getElements().size());
777 newElements.push_back(
778 {elt.name, elt.isFlip, elt.type.getWidthlessType()});
779 return BundleType::get(this->getContext(), newElements, a.isConst());
781 .Case<FVectorType>([](
auto a) {
782 return FVectorType::get(a.getElementType().getWidthlessType(),
783 a.getNumElements(), a.isConst());
785 .Case<FEnumType>([&](FEnumType a) {
786 SmallVector<FEnumType::EnumElement, 4> newElements;
787 newElements.reserve(a.getNumElements());
789 newElements.push_back({elt.name, elt.type.getWidthlessType()});
790 return FEnumType::get(this->getContext(), newElements, a.isConst());
792 .Case<BaseTypeAliasType>([](BaseTypeAliasType type) {
793 return type.getModifiedType(type.getInnerType().getWidthlessType());
796 llvm_unreachable(
"unknown FIRRTL type");
806 return TypeSwitch<FIRRTLBaseType, int32_t>(*
this)
807 .Case<ClockType, ResetType, AsyncResetType>([](Type) {
return 1; })
808 .Case<SIntType, UIntType>(
811 [](AnalogType analogType) {
return analogType.getWidthOrSentinel(); })
812 .Case<BundleType, FVectorType, FEnumType>([](Type) {
return -2; })
813 .Case<BaseTypeAliasType>([](BaseTypeAliasType type) {
815 return type.getAnonymousType().getBitWidthOrSentinel();
818 llvm_unreachable(
"unknown FIRRTL type");
827 return TypeSwitch<FIRRTLType, bool>(*
this)
828 .Case<ResetType, AsyncResetType>([](Type) {
return true; })
830 [](UIntType a) {
return !a.hasWidth() || a.getWidth() == 1; })
831 .Case<BaseTypeAliasType>(
832 [](
auto type) {
return type.getInnerType().isResetType(); })
833 .Default([](Type) {
return false; });
837 return TypeSwitch<Type, bool>(type)
839 [](
auto base) {
return base.isConst(); })
844 return TypeSwitch<Type, bool>(type)
846 [](
auto base) {
return base.containsConst(); })
853 .
Case<BundleType>([&](
auto bundle) {
854 for (
size_t i = 0, e = bundle.getNumElements(); i < e; ++i) {
855 auto elt = bundle.getElement(i);
859 return bundle.getNumElements() == 0;
861 .Case<FVectorType>([&](
auto vector) {
862 if (vector.getNumElements() == 0)
866 .Case<FIRRTLBaseType>([](
auto groundType) {
869 .Case<RefType>([](
auto ref) {
return hasZeroBitWidth(ref.getType()); })
870 .Default([](
auto) {
return false; });
880 BundleType::BundleElement srcElement,
881 bool destOuterTypeIsConst,
882 bool srcOuterTypeIsConst,
883 bool requiresSameWidth) {
884 if (destElement.name != srcElement.name)
886 if (destElement.isFlip != srcElement.isFlip)
889 if (destElement.isFlip) {
890 std::swap(destElement, srcElement);
891 std::swap(destOuterTypeIsConst, srcOuterTypeIsConst);
895 destOuterTypeIsConst, srcOuterTypeIsConst,
904 bool destOuterTypeIsConst,
905 bool srcOuterTypeIsConst,
906 bool requireSameWidths) {
907 auto destType = type_dyn_cast<FIRRTLBaseType>(destFType);
908 auto srcType = type_dyn_cast<FIRRTLBaseType>(srcFType);
911 if (!destType || !srcType)
912 return destFType == srcFType;
914 bool srcIsConst = srcOuterTypeIsConst || srcFType.
isConst();
915 bool destIsConst = destOuterTypeIsConst || destFType.
isConst();
918 auto destVectorType = type_dyn_cast<FVectorType>(destType);
919 auto srcVectorType = type_dyn_cast<FVectorType>(srcType);
920 if (destVectorType && srcVectorType)
921 return destVectorType.getNumElements() == srcVectorType.getNumElements() &&
923 srcVectorType.getElementType(), destIsConst,
924 srcIsConst, requireSameWidths);
928 auto destBundleType = type_dyn_cast<BundleType>(destType);
929 auto srcBundleType = type_dyn_cast<BundleType>(srcType);
930 if (destBundleType && srcBundleType) {
931 auto destElements = destBundleType.getElements();
932 auto srcElements = srcBundleType.getElements();
933 size_t numDestElements = destElements.size();
934 if (numDestElements != srcElements.size())
937 for (
size_t i = 0; i < numDestElements; ++i) {
938 auto destElement = destElements[i];
939 auto srcElement = srcElements[i];
941 srcIsConst, requireSameWidths))
949 auto dstEnumType = type_dyn_cast<FEnumType>(destType);
950 auto srcEnumType = type_dyn_cast<FEnumType>(srcType);
952 if (dstEnumType && srcEnumType) {
953 if (dstEnumType.getNumElements() != srcEnumType.getNumElements())
956 for (
const auto &[dst, src] : llvm::zip(dstEnumType, srcEnumType)) {
958 if (dst.name != src.name)
970 if (destIsConst && !srcIsConst)
974 if (firrtl::type_isa<ResetType>(destType))
975 return srcType.isResetType();
978 if (firrtl::type_isa<ResetType>(srcType))
979 return destType.isResetType();
983 if (!requireSameWidths || destType.getBitWidthOrSentinel() == -1)
984 srcType = srcType.getWidthlessType();
985 if (!requireSameWidths || srcType.getBitWidthOrSentinel() == -1)
986 destType = destType.getWidthlessType();
989 return destType.getConstType(
false) == srcType.getConstType(
false);
994 bool srcOuterTypeIsConst) {
996 if (destFType == srcFType)
999 auto destType = type_dyn_cast<FIRRTLBaseType>(destFType);
1000 auto srcType = type_dyn_cast<FIRRTLBaseType>(srcFType);
1003 if (!destType || !srcType)
1007 if (!destType.isPassive() || !srcType.isPassive())
1010 bool srcIsConst = srcType.isConst() || srcOuterTypeIsConst;
1013 if (destType.isConst() && !srcIsConst)
1018 auto destVectorType = type_dyn_cast<FVectorType>(destType);
1019 auto srcVectorType = type_dyn_cast<FVectorType>(srcType);
1020 if (destVectorType && srcVectorType)
1021 return destVectorType.getNumElements() == srcVectorType.getNumElements() &&
1023 srcVectorType.getElementType(), srcIsConst);
1024 if (destVectorType != srcVectorType)
1029 auto destBundleType = type_dyn_cast<BundleType>(destType);
1030 auto srcBundleType = type_dyn_cast<BundleType>(srcType);
1031 if (destBundleType && srcBundleType) {
1032 auto destElements = destBundleType.getElements();
1033 auto srcElements = srcBundleType.getElements();
1034 size_t numDestElements = destElements.size();
1035 if (numDestElements != srcElements.size())
1038 return llvm::all_of_zip(
1039 destElements, srcElements,
1040 [&](
const auto &destElement,
const auto &srcElement) {
1041 return destElement.name == srcElement.name &&
1046 if (destBundleType != srcBundleType)
1051 return destType == srcType.getConstType(destType.isConst());
1055 auto dstRefType = type_dyn_cast<RefType>(dstType);
1056 auto srcRefType = type_dyn_cast<RefType>(srcType);
1057 if (!dstRefType || !srcRefType)
1059 if (dstRefType == srcRefType)
1061 if (dstRefType.getForceable() && !srcRefType.getForceable())
1073 bool srcOuterTypeIsConst) ->
bool {
1079 assert(dest.isPassive() && src.isPassive());
1081 bool srcIsConst = src.isConst() || srcOuterTypeIsConst;
1084 if (dest.isConst() && !srcIsConst)
1090 if (
auto destVectorType = type_dyn_cast<FVectorType>(dest)) {
1091 auto srcVectorType = type_dyn_cast<FVectorType>(src);
1092 return srcVectorType &&
1093 destVectorType.getNumElements() ==
1094 srcVectorType.getNumElements() &&
1095 f(f, destVectorType.getElementType(),
1096 srcVectorType.getElementType(), srcIsConst);
1099 if (
auto destBundleType = type_dyn_cast<BundleType>(dest)) {
1100 auto srcBundleType = type_dyn_cast<BundleType>(src);
1104 auto destElements = destBundleType.getElements();
1105 auto srcElements = srcBundleType.getElements();
1107 return destElements.size() == srcElements.size() &&
1109 destElements, srcElements,
1110 [&](
const auto &destElement,
const auto &srcElement) {
1111 return destElement.name == srcElement.name &&
1112 f(f, destElement.type, srcElement.type, srcIsConst);
1116 if (
auto destEnumType = type_dyn_cast<FEnumType>(dest)) {
1117 auto srcEnumType = type_dyn_cast<FEnumType>(src);
1120 auto destElements = destEnumType.getElements();
1121 auto srcElements = srcEnumType.getElements();
1123 return destElements.size() == srcElements.size() &&
1125 destElements, srcElements,
1126 [&](
const auto &destElement,
const auto &srcElement) {
1127 return destElement.name == srcElement.name &&
1128 f(f, destElement.type, srcElement.type, srcIsConst);
1133 if (type_isa<ResetType>(dest))
1134 return src.isResetType();
1138 src = src.getConstType(dest.isConst());
1141 if (dest.getBitWidthOrSentinel() == -1)
1142 src = src.getWidthlessType();
1147 return recurse(recurse, dstRefType.getType(), srcRefType.getType(),
false);
1154 return TypeSwitch<FIRRTLBaseType, bool>(dstType)
1155 .Case<BundleType>([&](
auto dstBundle) {
1156 auto srcBundle = type_cast<BundleType>(srcType);
1157 for (
size_t i = 0, n = dstBundle.getNumElements(); i < n; ++i) {
1158 auto srcElem = srcBundle.getElement(i);
1159 auto dstElem = dstBundle.getElement(i);
1160 if (dstElem.isFlip) {
1170 .Case<FVectorType>([&](
auto vector) {
1172 type_cast<FVectorType>(srcType).getElementType());
1174 .Default([&](
auto dstGround) {
1177 return destWidth <= -1 || srcWidth <= -1 || destWidth >= srcWidth;
1188 if (
auto destBaseType = type_dyn_cast<FIRRTLBaseType>(lhs))
1189 if (
auto srcBaseType = type_dyn_cast<FIRRTLBaseType>(rhs))
1192 if (
auto destRefType = type_dyn_cast<RefType>(lhs))
1193 if (
auto srcRefType = type_dyn_cast<RefType>(rhs))
1195 srcRefType.getType());
1203 return type_cast<FIRRTLBaseType>(anyBaseFIRRTLType).getPassiveType();
1207 return llvm::TypeSwitch<Type, bool>(type)
1209 return !type.containsReference() &&
1210 (!type.isPassive() || type.containsAnalog());
1222 int32_t widthOrSentinel,
bool isConst) {
1224 return SIntType::get(context, widthOrSentinel,
isConst);
1225 return UIntType::get(context, widthOrSentinel,
isConst);
1229 if (
auto sintType = type_dyn_cast<SIntType>(*
this))
1230 return sintType.getWidthOrSentinel();
1231 if (
auto uintType = type_dyn_cast<UIntType>(*
this))
1232 return uintType.getWidthOrSentinel();
1260 if (
auto sIntType = type_dyn_cast<SIntType>(*
this))
1269SIntType SIntType::get(MLIRContext *context) {
return get(context, -1,
false); }
1271SIntType SIntType::get(MLIRContext *context, std::optional<int32_t> width,
1273 return get(context, width ? *width : -1,
isConst);
1276LogicalResult SIntType::verify(function_ref<InFlightDiagnostic()> emitError,
1277 int32_t widthOrSentinel,
bool isConst) {
1278 if (widthOrSentinel < -1)
1279 return emitError() <<
"invalid width";
1283int32_t SIntType::getWidthOrSentinel()
const {
return getImpl()->width; }
1285SIntType SIntType::getConstType(
bool isConst) {
1288 return get(getContext(), getWidthOrSentinel(),
isConst);
1295UIntType UIntType::get(MLIRContext *context) {
return get(context, -1,
false); }
1297UIntType UIntType::get(MLIRContext *context, std::optional<int32_t> width,
1299 return get(context, width ? *width : -1,
isConst);
1302LogicalResult UIntType::verify(function_ref<InFlightDiagnostic()> emitError,
1303 int32_t widthOrSentinel,
bool isConst) {
1304 if (widthOrSentinel < -1)
1305 return emitError() <<
"invalid width";
1309int32_t UIntType::getWidthOrSentinel()
const {
return getImpl()->width; }
1311UIntType UIntType::getConstType(
bool isConst) {
1314 return get(getContext(), getWidthOrSentinel(),
isConst);
1323 using KeyTy = std::pair<ArrayRef<BundleType::BundleElement>,
char>;
1330 uint64_t fieldID = 0;
1333 auto type = element.type;
1334 auto eltInfo = type.getRecursiveTypeProperties();
1355 return llvm::hash_combine(
1356 llvm::hash_combine_range(key.first.begin(), key.first.end()),
1377BundleType BundleType::get(MLIRContext *context,
1378 ArrayRef<BundleElement> elements,
bool isConst) {
1379 return Base::get(context, elements,
isConst);
1382auto BundleType::getElements() const -> ArrayRef<BundleElement> {
1383 return getImpl()->elements;
1388 return getImpl()->props;
1393 auto *impl = getImpl();
1396 if (impl->passiveType)
1397 return impl->passiveType;
1400 if (impl->props.isPassive) {
1401 impl->passiveType = *
this;
1406 SmallVector<BundleType::BundleElement, 16> newElements;
1407 newElements.reserve(impl->elements.size());
1408 for (
auto &elt : impl->elements) {
1409 newElements.push_back({elt.name,
false, elt.type.getPassiveType()});
1412 auto passiveType = BundleType::get(getContext(), newElements,
isConst());
1413 impl->passiveType = passiveType;
1417BundleType BundleType::getConstType(
bool isConst) {
1420 return get(getContext(), getElements(),
isConst);
1423BundleType BundleType::getAllConstDroppedType() {
1427 SmallVector<BundleElement> constDroppedElements(
1428 llvm::map_range(getElements(), [](BundleElement element) {
1429 element.type = element.type.getAllConstDroppedType();
1432 return get(getContext(), constDroppedElements,
false);
1435std::optional<unsigned> BundleType::getElementIndex(StringAttr name) {
1436 for (
const auto &it :
llvm::enumerate(getElements())) {
1437 auto element = it.value();
1438 if (element.name == name) {
1439 return unsigned(it.index());
1442 return std::nullopt;
1445std::optional<unsigned> BundleType::getElementIndex(StringRef name) {
1446 for (
const auto &it :
llvm::enumerate(getElements())) {
1447 auto element = it.value();
1448 if (element.name.getValue() == name) {
1449 return unsigned(it.index());
1452 return std::nullopt;
1455StringAttr BundleType::getElementNameAttr(
size_t index) {
1456 assert(index < getNumElements() &&
1457 "index must be less than number of fields in bundle");
1458 return getElements()[index].name;
1461StringRef BundleType::getElementName(
size_t index) {
1462 return getElementNameAttr(index).getValue();
1465std::optional<BundleType::BundleElement>
1466BundleType::getElement(StringAttr name) {
1467 if (
auto maybeIndex = getElementIndex(name))
1468 return getElements()[*maybeIndex];
1469 return std::nullopt;
1472std::optional<BundleType::BundleElement>
1473BundleType::getElement(StringRef name) {
1474 if (
auto maybeIndex = getElementIndex(name))
1475 return getElements()[*maybeIndex];
1476 return std::nullopt;
1480BundleType::BundleElement BundleType::getElement(
size_t index) {
1481 assert(index < getNumElements() &&
1482 "index must be less than number of fields in bundle");
1483 return getElements()[index];
1487 auto element = getElement(name);
1492 auto element = getElement(name);
1497 assert(index < getNumElements() &&
1498 "index must be less than number of fields in bundle");
1499 return getElements()[index].type;
1502uint64_t BundleType::getFieldID(uint64_t index)
const {
1503 return getImpl()->fieldIDs[index];
1506uint64_t BundleType::getIndexForFieldID(uint64_t fieldID)
const {
1507 assert(!getElements().
empty() &&
"Bundle must have >0 fields");
1508 auto fieldIDs = getImpl()->fieldIDs;
1509 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
1510 return std::distance(fieldIDs.begin(), it);
1513std::pair<uint64_t, uint64_t>
1514BundleType::getIndexAndSubfieldID(uint64_t fieldID)
const {
1517 return {index, fieldID - elementFieldID};
1520std::pair<Type, uint64_t>
1521BundleType::getSubTypeByFieldID(uint64_t fieldID)
const {
1525 auto subfieldType = getElementType(subfieldIndex);
1526 auto subfieldID = fieldID -
getFieldID(subfieldIndex);
1527 return {subfieldType, subfieldID};
1530uint64_t BundleType::getMaxFieldID()
const {
return getImpl()->maxFieldID; }
1532std::pair<uint64_t, bool>
1533BundleType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
1535 auto rangeEnd = index + 1 >= getNumElements() ?
getMaxFieldID()
1537 return std::make_pair(fieldID - childRoot,
1538 fieldID >= childRoot && fieldID <= rangeEnd);
1541bool BundleType::isConst() {
return getImpl()->isConst; }
1543BundleType::ElementType
1544BundleType::getElementTypePreservingConst(
size_t index) {
1545 auto type = getElementType(index);
1546 return type.getConstType(type.isConst() ||
isConst());
1551 auto *impl = getImpl();
1554 if (impl->anonymousType)
1555 return impl->anonymousType;
1558 if (!impl->props.containsTypeAlias) {
1559 impl->anonymousType = *
this;
1565 SmallVector<BundleType::BundleElement, 16> newElements;
1566 newElements.reserve(impl->elements.size());
1567 for (
auto &elt : impl->elements)
1568 newElements.push_back({elt.name, elt.isFlip, elt.type.getAnonymousType()});
1570 auto anonymousType = BundleType::get(getContext(), newElements,
isConst());
1571 impl->anonymousType = anonymousType;
1572 return anonymousType;
1580 using KeyTy = std::pair<ArrayRef<OpenBundleType::BundleElement>,
char>;
1588 uint64_t fieldID = 0;
1591 auto type = element.type;
1592 auto eltInfo = type.getRecursiveTypeProperties();
1612 return llvm::hash_combine(
1613 llvm::hash_combine_range(key.first.begin(), key.first.end()),
1625 SmallVector<OpenBundleType::BundleElement, 4>
elements;
1637OpenBundleType OpenBundleType::get(MLIRContext *context,
1638 ArrayRef<BundleElement> elements,
1640 return Base::get(context, elements,
isConst);
1643auto OpenBundleType::getElements() const -> ArrayRef<BundleElement> {
1644 return getImpl()->elements;
1649 return getImpl()->props;
1652OpenBundleType OpenBundleType::getConstType(
bool isConst) {
1655 return get(getContext(), getElements(),
isConst);
1658std::optional<unsigned> OpenBundleType::getElementIndex(StringAttr name) {
1659 for (
const auto &it :
llvm::enumerate(getElements())) {
1660 auto element = it.value();
1661 if (element.name == name) {
1662 return unsigned(it.index());
1665 return std::nullopt;
1668std::optional<unsigned> OpenBundleType::getElementIndex(StringRef name) {
1669 for (
const auto &it :
llvm::enumerate(getElements())) {
1670 auto element = it.value();
1671 if (element.name.getValue() == name) {
1672 return unsigned(it.index());
1675 return std::nullopt;
1678StringAttr OpenBundleType::getElementNameAttr(
size_t index) {
1679 assert(index < getNumElements() &&
1680 "index must be less than number of fields in bundle");
1681 return getElements()[index].name;
1684StringRef OpenBundleType::getElementName(
size_t index) {
1685 return getElementNameAttr(index).getValue();
1688std::optional<OpenBundleType::BundleElement>
1689OpenBundleType::getElement(StringAttr name) {
1690 if (
auto maybeIndex = getElementIndex(name))
1691 return getElements()[*maybeIndex];
1692 return std::nullopt;
1695std::optional<OpenBundleType::BundleElement>
1696OpenBundleType::getElement(StringRef name) {
1697 if (
auto maybeIndex = getElementIndex(name))
1698 return getElements()[*maybeIndex];
1699 return std::nullopt;
1703OpenBundleType::BundleElement OpenBundleType::getElement(
size_t index) {
1704 assert(index < getNumElements() &&
1705 "index must be less than number of fields in bundle");
1706 return getElements()[index];
1709OpenBundleType::ElementType OpenBundleType::getElementType(StringAttr name) {
1710 auto element = getElement(name);
1714OpenBundleType::ElementType OpenBundleType::getElementType(StringRef name) {
1715 auto element = getElement(name);
1719OpenBundleType::ElementType OpenBundleType::getElementType(
size_t index)
const {
1720 assert(index < getNumElements() &&
1721 "index must be less than number of fields in bundle");
1722 return getElements()[index].type;
1725uint64_t OpenBundleType::getFieldID(uint64_t index)
const {
1726 return getImpl()->fieldIDs[index];
1729uint64_t OpenBundleType::getIndexForFieldID(uint64_t fieldID)
const {
1730 assert(!getElements().
empty() &&
"Bundle must have >0 fields");
1731 auto fieldIDs = getImpl()->fieldIDs;
1732 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
1733 return std::distance(fieldIDs.begin(), it);
1736std::pair<uint64_t, uint64_t>
1737OpenBundleType::getIndexAndSubfieldID(uint64_t fieldID)
const {
1740 return {index, fieldID - elementFieldID};
1743std::pair<Type, uint64_t>
1744OpenBundleType::getSubTypeByFieldID(uint64_t fieldID)
const {
1748 auto subfieldType = getElementType(subfieldIndex);
1749 auto subfieldID = fieldID -
getFieldID(subfieldIndex);
1750 return {subfieldType, subfieldID};
1753uint64_t OpenBundleType::getMaxFieldID()
const {
return getImpl()->maxFieldID; }
1755std::pair<uint64_t, bool>
1756OpenBundleType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
1758 auto rangeEnd = index + 1 >= getNumElements() ?
getMaxFieldID()
1760 return std::make_pair(fieldID - childRoot,
1761 fieldID >= childRoot && fieldID <= rangeEnd);
1764bool OpenBundleType::isConst() {
return getImpl()->isConst; }
1766OpenBundleType::ElementType
1767OpenBundleType::getElementTypePreservingConst(
size_t index) {
1768 auto type = getElementType(index);
1770 return TypeSwitch<FIRRTLType, ElementType>(type)
1771 .Case<
FIRRTLBaseType, OpenBundleType, OpenVectorType>([&](
auto type) {
1772 return type.getConstType(type.isConst() ||
isConst());
1778OpenBundleType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
1779 ArrayRef<BundleElement> elements,
bool isConst) {
1780 for (
auto &element : elements) {
1782 return emitErrorFn()
1783 <<
"'const' bundle cannot have references, but element "
1784 << element.name <<
" has type " << element.type;
1785 if (type_isa<LHSType>(element.type))
1786 return emitErrorFn() <<
"bundle element " << element.name
1787 <<
" cannot have a left-hand side type";
1799 using KeyTy = std::tuple<FIRRTLBaseType, size_t, char>;
1817 static_cast<bool>(std::get<2>(key)));
1836 return getImpl()->elementType;
1839size_t FVectorType::getNumElements()
const {
return getImpl()->numElements; }
1843 return getImpl()->props;
1848 auto *impl = getImpl();
1851 if (impl->passiveType)
1852 return impl->passiveType;
1855 if (impl->elementType.getRecursiveTypeProperties().isPassive)
1856 return impl->passiveType = *
this;
1859 auto passiveType = FVectorType::get(getElementType().
getPassiveType(),
1861 impl->passiveType = passiveType;
1865FVectorType FVectorType::getConstType(
bool isConst) {
1868 return get(getElementType(), getNumElements(),
isConst);
1871FVectorType FVectorType::getAllConstDroppedType() {
1874 return get(getElementType().getAllConstDroppedType(), getNumElements(),
1880 auto *impl = getImpl();
1882 if (impl->anonymousType)
1883 return impl->anonymousType;
1886 if (!impl->props.containsTypeAlias)
1887 return impl->anonymousType = *
this;
1890 auto anonymousType = FVectorType::get(getElementType().getAnonymousType(),
1892 impl->anonymousType = anonymousType;
1893 return anonymousType;
1896uint64_t FVectorType::getFieldID(uint64_t index)
const {
1900uint64_t FVectorType::getIndexForFieldID(uint64_t fieldID)
const {
1901 assert(fieldID &&
"fieldID must be at least 1");
1906std::pair<uint64_t, uint64_t>
1907FVectorType::getIndexAndSubfieldID(uint64_t fieldID)
const {
1910 return {index, fieldID - elementFieldID};
1913std::pair<Type, uint64_t>
1914FVectorType::getSubTypeByFieldID(uint64_t fieldID)
const {
1920uint64_t FVectorType::getMaxFieldID()
const {
1921 return getNumElements() *
1925std::pair<uint64_t, bool>
1926FVectorType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
1930 return std::make_pair(fieldID - childRoot,
1931 fieldID >= childRoot && fieldID <= rangeEnd);
1934bool FVectorType::isConst() {
return getImpl()->isConst; }
1936FVectorType::ElementType FVectorType::getElementTypePreservingConst() {
1937 auto type = getElementType();
1938 return type.getConstType(type.isConst() ||
isConst());
1946 using KeyTy = std::tuple<FIRRTLType, size_t, char>;
1964 static_cast<bool>(std::get<2>(key)));
1979FIRRTLType OpenVectorType::getElementType()
const {
1980 return getImpl()->elementType;
1983size_t OpenVectorType::getNumElements()
const {
return getImpl()->numElements; }
1987 return getImpl()->props;
1990OpenVectorType OpenVectorType::getConstType(
bool isConst) {
1993 return get(getElementType(), getNumElements(),
isConst);
1996uint64_t OpenVectorType::getFieldID(uint64_t index)
const {
2000uint64_t OpenVectorType::getIndexForFieldID(uint64_t fieldID)
const {
2001 assert(fieldID &&
"fieldID must be at least 1");
2006std::pair<uint64_t, uint64_t>
2007OpenVectorType::getIndexAndSubfieldID(uint64_t fieldID)
const {
2010 return {index, fieldID - elementFieldID};
2013std::pair<Type, uint64_t>
2014OpenVectorType::getSubTypeByFieldID(uint64_t fieldID)
const {
2020uint64_t OpenVectorType::getMaxFieldID()
const {
2022 return getNumElements() *
2026std::pair<uint64_t, bool>
2027OpenVectorType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
2031 return std::make_pair(fieldID - childRoot,
2032 fieldID >= childRoot && fieldID <= rangeEnd);
2035bool OpenVectorType::isConst() {
return getImpl()->isConst; }
2037OpenVectorType::ElementType OpenVectorType::getElementTypePreservingConst() {
2038 auto type = getElementType();
2040 return TypeSwitch<FIRRTLType, ElementType>(type)
2041 .Case<
FIRRTLBaseType, OpenBundleType, OpenVectorType>([&](
auto type) {
2042 return type.getConstType(type.isConst() ||
isConst());
2048OpenVectorType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
2052 return emitErrorFn() <<
"vector cannot be const with references";
2054 return emitErrorFn() <<
"vector cannot have a left-hand side type";
2063 using KeyTy = std::pair<ArrayRef<FEnumType::EnumElement>,
char>;
2069 false,
false,
false};
2070 uint64_t fieldID = 0;
2073 auto type = element.type;
2074 auto eltInfo = type.getRecursiveTypeProperties();
2076 props.containsAnalog |= eltInfo.containsAnalog;
2077 props.containsConst |= eltInfo.containsConst;
2078 props.containsReference |= eltInfo.containsReference;
2079 props.containsTypeAlias |= eltInfo.containsTypeAlias;
2080 props.hasUninferredReset |= eltInfo.hasUninferredReset;
2081 props.hasUninferredWidth |= eltInfo.hasUninferredWidth;
2096 return llvm::hash_combine(
2097 llvm::hash_combine_range(key.first.begin(), key.first.end()),
2115FEnumType FEnumType::get(::mlir::MLIRContext *context,
2116 ArrayRef<EnumElement> elements,
bool isConst) {
2117 return Base::get(context, elements,
isConst);
2120ArrayRef<FEnumType::EnumElement> FEnumType::getElements()
const {
2121 return getImpl()->elements;
2124FEnumType FEnumType::getConstType(
bool isConst) {
2125 return get(getContext(), getElements(),
isConst);
2128FEnumType FEnumType::getAllConstDroppedType() {
2132 SmallVector<EnumElement> constDroppedElements(
2133 llvm::map_range(getElements(), [](EnumElement element) {
2134 element.type = element.type.getAllConstDroppedType();
2137 return get(getContext(), constDroppedElements,
false);
2142 return getImpl()->recProps;
2145std::optional<unsigned> FEnumType::getElementIndex(StringAttr name) {
2146 for (
const auto &it :
llvm::enumerate(getElements())) {
2147 auto element = it.value();
2148 if (element.name == name) {
2149 return unsigned(it.index());
2152 return std::nullopt;
2155std::optional<unsigned> FEnumType::getElementIndex(StringRef name) {
2156 for (
const auto &it :
llvm::enumerate(getElements())) {
2157 auto element = it.value();
2158 if (element.name.getValue() == name) {
2159 return unsigned(it.index());
2162 return std::nullopt;
2165StringAttr FEnumType::getElementNameAttr(
size_t index) {
2166 assert(index < getNumElements() &&
2167 "index must be less than number of fields in enum");
2168 return getElements()[index].name;
2171StringRef FEnumType::getElementName(
size_t index) {
2172 return getElementNameAttr(index).getValue();
2175std::optional<FEnumType::EnumElement> FEnumType::getElement(StringAttr name) {
2176 if (
auto maybeIndex = getElementIndex(name))
2177 return getElements()[*maybeIndex];
2178 return std::nullopt;
2181std::optional<FEnumType::EnumElement> FEnumType::getElement(StringRef name) {
2182 if (
auto maybeIndex = getElementIndex(name))
2183 return getElements()[*maybeIndex];
2184 return std::nullopt;
2188FEnumType::EnumElement FEnumType::getElement(
size_t index) {
2189 assert(index < getNumElements() &&
2190 "index must be less than number of fields in enum");
2191 return getElements()[index];
2195 auto element = getElement(name);
2200 auto element = getElement(name);
2205 assert(index < getNumElements() &&
2206 "index must be less than number of fields in enum");
2207 return getElements()[index].type;
2210FIRRTLBaseType FEnumType::getElementTypePreservingConst(
size_t index) {
2211 auto type = getElementType(index);
2212 return type.getConstType(type.isConst() ||
isConst());
2215uint64_t FEnumType::getFieldID(uint64_t index)
const {
2216 return getImpl()->fieldIDs[index];
2219uint64_t FEnumType::getIndexForFieldID(uint64_t fieldID)
const {
2220 assert(!getElements().
empty() &&
"Enum must have >0 fields");
2221 auto fieldIDs = getImpl()->fieldIDs;
2222 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
2223 return std::distance(fieldIDs.begin(), it);
2226std::pair<uint64_t, uint64_t>
2227FEnumType::getIndexAndSubfieldID(uint64_t fieldID)
const {
2230 return {index, fieldID - elementFieldID};
2233std::pair<Type, uint64_t>
2234FEnumType::getSubTypeByFieldID(uint64_t fieldID)
const {
2238 auto subfieldType = getElementType(subfieldIndex);
2239 auto subfieldID = fieldID -
getFieldID(subfieldIndex);
2240 return {subfieldType, subfieldID};
2243uint64_t FEnumType::getMaxFieldID()
const {
return getImpl()->maxFieldID; }
2245std::pair<uint64_t, bool>
2246FEnumType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
2248 auto rangeEnd = index + 1 >= getNumElements() ?
getMaxFieldID()
2250 return std::make_pair(fieldID - childRoot,
2251 fieldID >= childRoot && fieldID <= rangeEnd);
2254auto FEnumType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
2255 ArrayRef<EnumElement> elements,
bool isConst)
2257 for (
auto &elt : elements) {
2258 auto r = elt.type.getRecursiveTypeProperties();
2260 return emitErrorFn() <<
"enum field '" << elt.name <<
"' not passive";
2261 if (r.containsAnalog)
2262 return emitErrorFn() <<
"enum field '" << elt.name <<
"' contains analog";
2263 if (r.containsConst && !
isConst)
2264 return emitErrorFn() <<
"enum with 'const' elements must be 'const'";
2272 auto *impl = getImpl();
2274 if (impl->anonymousType)
2275 return impl->anonymousType;
2277 if (!impl->recProps.containsTypeAlias)
2278 return impl->anonymousType = *
this;
2280 SmallVector<FEnumType::EnumElement, 4> elements;
2282 for (
auto element : getElements())
2283 elements.push_back({element.name, element.type.getAnonymousType()});
2284 return impl->anonymousType = FEnumType::get(getContext(), elements);
2293 using KeyTy = std::tuple<StringAttr, FIRRTLBaseType>;
2304 return llvm::hash_combine(key);
2317auto BaseTypeAliasType::get(StringAttr name,
FIRRTLBaseType innerType)
2318 -> BaseTypeAliasType {
2319 return Base::get(name.getContext(), name, innerType);
2322auto BaseTypeAliasType::getName() const -> StringAttr {
2323 return getImpl()->name;
2327 return getImpl()->innerType;
2331 auto *impl = getImpl();
2332 if (impl->anonymousType)
2333 return impl->anonymousType;
2334 return impl->anonymousType = getInnerType().getAnonymousType();
2342 auto rtp = getInnerType().getRecursiveTypeProperties();
2350 if (newInnerType == getInnerType())
2352 return newInnerType;
2357 return getModifiedType(getInnerType().getAllConstDroppedType());
2361 return getModifiedType(getInnerType().getConstType(
isConst));
2364std::pair<Type, uint64_t>
2365BaseTypeAliasType::getSubTypeByFieldID(uint64_t fieldID)
const {
2369uint64_t BaseTypeAliasType::getMaxFieldID()
const {
2373std::pair<uint64_t, bool>
2374BaseTypeAliasType::projectToChildFieldID(uint64_t fieldID,
2375 uint64_t index)
const {
2379uint64_t BaseTypeAliasType::getIndexForFieldID(uint64_t fieldID)
const {
2383uint64_t BaseTypeAliasType::getFieldID(uint64_t index)
const {
2387std::pair<uint64_t, uint64_t>
2388BaseTypeAliasType::getIndexAndSubfieldID(uint64_t fieldID)
const {
2397 return LHSType::get(type.getContext(), type);
2400LogicalResult LHSType::verify(function_ref<InFlightDiagnostic()> emitError,
2402 if (type.containsAnalog())
2403 return emitError() <<
"lhs type cannot contain an AnalogType";
2405 return emitError() <<
"lhs type cannot contain a non-passive type";
2406 if (type.containsReference())
2407 return emitError() <<
"lhs type cannot contain a reference";
2408 if (type_isa<LHSType>(type))
2409 return emitError() <<
"lhs type cannot contain a lhs type";
2418auto RefType::get(
FIRRTLBaseType type,
bool forceable, SymbolRefAttr layer)
2420 return Base::get(type.getContext(), type, forceable, layer);
2423auto RefType::verify(function_ref<InFlightDiagnostic()> emitErrorFn,
2426 if (!base.isPassive())
2427 return emitErrorFn() <<
"reference base type must be passive";
2428 if (forceable && base.containsConst())
2429 return emitErrorFn()
2430 <<
"forceable reference base type cannot contain const";
2435 auto rtp = getType().getRecursiveTypeProperties();
2438 rtp.isPassive =
false;
2446AnalogType AnalogType::get(mlir::MLIRContext *context) {
2447 return AnalogType::get(context, -1,
false);
2450AnalogType AnalogType::get(mlir::MLIRContext *context,
2451 std::optional<int32_t> width,
bool isConst) {
2452 return AnalogType::get(context, width ? *width : -1,
isConst);
2455LogicalResult AnalogType::verify(function_ref<InFlightDiagnostic()> emitError,
2456 int32_t widthOrSentinel,
bool isConst) {
2457 if (widthOrSentinel < -1)
2458 return emitError() <<
"invalid width";
2462int32_t AnalogType::getWidthOrSentinel()
const {
return getImpl()->width; }
2464AnalogType AnalogType::getConstType(
bool isConst) {
2467 return get(getContext(), getWidthOrSentinel(),
isConst);
2474ClockType ClockType::getConstType(
bool isConst) {
2484ResetType ResetType::getConstType(
bool isConst) {
2494AsyncResetType AsyncResetType::getConstType(
bool isConst) {
2505 using KeyTy = std::pair<FlatSymbolRefAttr, ArrayRef<ClassElement>>;
2509 auto name = key.first;
2510 auto elements = allocator.copyInto(key.second);
2513 SmallVector<uint64_t, 4> ids;
2522 auto fieldIDs = allocator.copyInto(ArrayRef(ids));
2544ClassType ClassType::get(FlatSymbolRefAttr name,
2545 ArrayRef<ClassElement> elements) {
2546 return get(name.getContext(), name, elements);
2549StringRef ClassType::getName()
const {
2550 return getNameAttr().getAttr().getValue();
2553FlatSymbolRefAttr ClassType::getNameAttr()
const {
return getImpl()->name; }
2555ArrayRef<ClassElement> ClassType::getElements()
const {
2556 return getImpl()->elements;
2559const ClassElement &ClassType::getElement(IntegerAttr index)
const {
2560 return getElement(index.getValue().getZExtValue());
2563const ClassElement &ClassType::getElement(
size_t index)
const {
2564 return getElements()[index];
2567std::optional<uint64_t> ClassType::getElementIndex(StringRef fieldName)
const {
2568 for (
const auto [i, e] :
llvm::enumerate(getElements()))
2569 if (fieldName == e.name)
2574void ClassType::printInterface(AsmPrinter &p)
const {
2578 for (
const auto &element : getElements()) {
2582 p.printKeywordOrString(element.name);
2583 p <<
": " << element.type;
2589uint64_t ClassType::getFieldID(uint64_t index)
const {
2590 return getImpl()->fieldIDs[index];
2593uint64_t ClassType::getIndexForFieldID(uint64_t fieldID)
const {
2594 assert(!getElements().
empty() &&
"Class must have >0 fields");
2595 auto fieldIDs = getImpl()->fieldIDs;
2596 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
2597 return std::distance(fieldIDs.begin(), it);
2600std::pair<uint64_t, uint64_t>
2601ClassType::getIndexAndSubfieldID(uint64_t fieldID)
const {
2604 return {index, fieldID - elementFieldID};
2607std::pair<Type, uint64_t>
2608ClassType::getSubTypeByFieldID(uint64_t fieldID)
const {
2612 auto subfieldType = getElement(subfieldIndex).type;
2613 auto subfieldID = fieldID -
getFieldID(subfieldIndex);
2614 return {subfieldType, subfieldID};
2617uint64_t ClassType::getMaxFieldID()
const {
return getImpl()->maxFieldID; }
2619std::pair<uint64_t, bool>
2620ClassType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
2622 auto rangeEnd = index + 1 >= getNumElements() ?
getMaxFieldID()
2624 return std::make_pair(fieldID - childRoot,
2625 fieldID >= childRoot && fieldID <= rangeEnd);
2628ParseResult ClassType::parseInterface(AsmParser &parser, ClassType &result) {
2629 StringAttr className;
2630 if (parser.parseSymbolName(className))
2633 SmallVector<ClassElement> elements;
2634 if (parser.parseCommaSeparatedList(
2635 OpAsmParser::Delimiter::Paren, [&]() -> ParseResult {
2637 Direction direction;
2638 if (succeeded(parser.parseOptionalKeyword(
"out")))
2639 direction = Direction::Out;
2640 else if (succeeded(parser.parseKeyword(
"in",
"or 'out'")))
2641 direction = Direction::In;
2646 std::string keyword;
2647 if (parser.parseKeywordOrString(&keyword))
2649 StringAttr name = StringAttr::get(parser.getContext(), keyword);
2653 if (parser.parseColonType(type))
2656 elements.emplace_back(name, type, direction);
2661 result = ClassType::get(FlatSymbolRefAttr::get(className), elements);
2669void FIRRTLDialect::registerTypes() {
2671#define GET_TYPEDEF_LIST
2672#include "circt/Dialect/FIRRTL/FIRRTLTypes.cpp.inc"
2686 return TypeSwitch<FIRRTLBaseType, std::optional<int64_t>>(type)
2687 .Case<BundleType>([&](BundleType bundle) -> std::optional<int64_t> {
2689 for (
auto &elt : bundle) {
2690 if (elt.isFlip && !ignoreFlip)
2691 return std::nullopt;
2694 return std::nullopt;
2699 .Case<FEnumType>([&](FEnumType fenum) -> std::optional<int64_t> {
2701 for (
auto &elt : fenum) {
2704 return std::nullopt;
2705 width = std::max(width, *w);
2707 return width + llvm::Log2_32_Ceil(fenum.getNumElements());
2709 .Case<FVectorType>([&](
auto vector) -> std::optional<int64_t> {
2712 return std::nullopt;
2713 return *w * vector.getNumElements();
2716 .Case<ClockType, ResetType, AsyncResetType>([](Type) {
return 1; })
2717 .Default([&](
auto t) {
return std::nullopt; });
2719 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)