19 #include "mlir/IR/Builders.h"
20 #include "mlir/IR/BuiltinTypes.h"
21 #include "mlir/IR/Diagnostics.h"
22 #include "mlir/IR/DialectImplementation.h"
23 #include "mlir/IR/StorageUniquerSupport.h"
24 #include "mlir/IR/Types.h"
25 #include "llvm/ADT/SmallSet.h"
26 #include "llvm/ADT/StringExtras.h"
27 #include "llvm/ADT/StringSet.h"
28 #include "llvm/ADT/TypeSwitch.h"
30 using namespace circt;
34 static ParseResult
parseHWArray(AsmParser &parser, Attribute &dim,
41 #define GET_TYPEDEF_CLASSES
42 #include "circt/Dialect/HW/HWTypes.cpp.inc"
50 if (
auto typeAlias = dyn_cast<TypeAliasType>(type))
51 canonicalType = typeAlias.getCanonicalType();
62 if (isa<hw::IntType>(canonicalType))
65 auto intType = dyn_cast<IntegerType>(canonicalType);
66 if (!intType || !intType.isSignless())
81 if (isa<IntegerType, IntType, EnumType>(type))
84 if (
auto array = dyn_cast<ArrayType>(type))
87 if (
auto array = dyn_cast<UnpackedArrayType>(type))
90 if (
auto t = dyn_cast<StructType>(type))
91 return llvm::all_of(t.getElements(),
92 [](
auto f) { return isHWValueType(f.type); });
94 if (
auto t = dyn_cast<UnionType>(type))
95 return llvm::all_of(t.getElements(),
96 [](
auto f) { return isHWValueType(f.type); });
98 if (
auto t = dyn_cast<TypeAliasType>(type))
110 return llvm::TypeSwitch<::mlir::Type, size_t>(type)
112 [](IntegerType t) {
return t.getIntOrFloatBitWidth(); })
113 .Case<ArrayType, UnpackedArrayType>([](
auto a) {
114 int64_t elementBitWidth =
getBitWidth(a.getElementType());
115 if (elementBitWidth < 0)
116 return elementBitWidth;
117 int64_t dimBitWidth = a.getNumElements();
119 return static_cast<int64_t
>(-1L);
120 return (int64_t)a.getNumElements() * elementBitWidth;
122 .Case<StructType>([](StructType s) {
124 for (
auto field : s.getElements()) {
132 .Case<UnionType>([](UnionType u) {
134 for (
auto field : u.getElements()) {
135 int64_t fieldSize =
getBitWidth(field.type) + field.offset;
136 if (fieldSize > maxSize)
141 .Case<EnumType>([](EnumType e) {
return e.getBitWidth(); })
142 .Case<TypeAliasType>(
143 [](TypeAliasType t) {
return getBitWidth(t.getCanonicalType()); })
144 .Default([](Type) {
return -1; });
151 if (
auto array = dyn_cast<ArrayType>(type))
154 if (
auto array = dyn_cast<UnpackedArrayType>(type))
157 if (
auto t = dyn_cast<StructType>(type)) {
158 return std::any_of(t.getElements().begin(), t.getElements().end(),
159 [](
const auto &f) { return hasHWInOutType(f.type); });
162 if (
auto t = dyn_cast<TypeAliasType>(type))
165 return isa<InOutType>(type);
174 auto fullString =
static_cast<DialectAsmParser &
>(p).getFullSymbolSpec();
175 auto *curPtr = p.getCurrentLocation().getPointer();
177 StringRef(curPtr, fullString.size() - (curPtr - fullString.data()));
179 if (typeString.starts_with(
"array<") || typeString.starts_with(
"inout<") ||
180 typeString.starts_with(
"uarray<") || typeString.starts_with(
"struct<") ||
181 typeString.starts_with(
"typealias<") || typeString.starts_with(
"int<") ||
182 typeString.starts_with(
"enum<")) {
183 llvm::StringRef mnemonic;
184 auto parseResult = generatedTypeParser(p, &mnemonic, result);
185 return parseResult.has_value() ? success() : failure();
188 return p.parseType(result);
192 if (succeeded(generatedTypePrinter(element, p)))
194 p.printType(element);
203 auto widthWidth = llvm::dyn_cast<IntegerType>(
width.getType());
204 assert(widthWidth && widthWidth.getWidth() == 32 &&
205 "!hw.int width must be 32-bits");
208 if (
auto cstWidth = llvm::dyn_cast<IntegerAttr>(
width))
210 cstWidth.getValue().getZExtValue());
215 Type IntType::parse(AsmParser &p) {
217 auto int32Type = p.getBuilder().getIntegerType(32);
219 mlir::TypedAttr
width;
220 if (p.parseLess() || p.parseAttribute(
width, int32Type) || p.parseGreater())
225 void IntType::print(AsmPrinter &p)
const {
227 p.printAttributeWithoutType(
getWidth());
231 //===----------------------------------------------------------------------===//
233 //===----------------------------------------------------------------------===//
238 bool operator==(const FieldInfo &a, const FieldInfo &b) {
239 return a.name == b.name && a.type == b.type;
241 llvm::hash_code hash_value(const FieldInfo &fi) {
242 return llvm::hash_combine(fi.name, fi.type);
244 } // namespace detail
250 static ParseResult parseFields(AsmParser &p,
251 SmallVectorImpl<FieldInfo> ¶meters) {
252 llvm::StringSet<> nameSet;
253 bool hasDuplicateName = false;
254 auto parseResult = p.parseCommaSeparatedList(
255 mlir::AsmParser::Delimiter::LessGreater, [&]() -> ParseResult {
259 auto fieldLoc = p.getCurrentLocation();
260 if (p.parseKeywordOrString(&name) || p.parseColon() ||
264 if (!nameSet.insert(name).second) {
265 p.emitError(fieldLoc, "duplicate field name \'" + name + "\'");
266 // Continue parsing to print all duplicates, but make sure to error
268 hasDuplicateName = true;
271 parameters.push_back(
272 FieldInfo{StringAttr::get(p.getContext(), name), type});
276 if (hasDuplicateName)
282 static void printFields(AsmPrinter &p, ArrayRef<FieldInfo> fields) {
284 llvm::interleaveComma(fields, p, [&](const FieldInfo &field) {
285 p.printKeywordOrString(field.name.getValue());
286 p << ": " << field.type;
291 Type StructType::parse(AsmParser &p) {
292 llvm::SmallVector<FieldInfo, 4> parameters;
293 if (parseFields(p, parameters))
295 return get(p.getContext(), parameters);
298 LogicalResult StructType::verify(function_ref<InFlightDiagnostic()> emitError,
299 ArrayRef<StructType::FieldInfo> elements) {
300 llvm::SmallDenseSet<StringAttr> fieldNameSet;
301 LogicalResult result = success();
302 fieldNameSet.reserve(elements.size());
303 for (const auto &elt : elements)
304 if (!fieldNameSet.insert(elt.name).second) {
306 emitError() << "duplicate field name '" << elt.name.getValue()
307 << "' in hw.struct type";
312 void StructType::print(AsmPrinter &p) const { printFields(p, getElements()); }
314 Type StructType::getFieldType(mlir::StringRef fieldName) {
315 for (const auto &field : getElements())
316 if (field.name == fieldName)
321 std::optional<uint32_t> StructType::getFieldIndex(mlir::StringRef fieldName) {
322 ArrayRef<hw::StructType::FieldInfo> elems = getElements();
323 for (size_t idx = 0, numElems = elems.size(); idx < numElems; ++idx)
324 if (elems[idx].name == fieldName)
329 std::optional<uint32_t> StructType::getFieldIndex(mlir::StringAttr fieldName) {
330 ArrayRef<hw::StructType::FieldInfo> elems = getElements();
331 for (size_t idx = 0, numElems = elems.size(); idx < numElems; ++idx)
332 if (elems[idx].name == fieldName)
337 static std::pair<uint64_t, SmallVector<uint64_t>>
338 getFieldIDsStruct(const StructType &st) {
339 uint64_t fieldID = 0;
340 auto elements = st.getElements();
341 SmallVector<uint64_t> fieldIDs;
342 fieldIDs.reserve(elements.size());
343 for (auto &element : elements) {
344 auto type = element.type;
346 fieldIDs.push_back(fieldID);
347 // Increment the field ID for the next field by the number of subfields.
348 fieldID += hw::FieldIdImpl::getMaxFieldID(type);
350 return {fieldID, fieldIDs};
353 void StructType::getInnerTypes(SmallVectorImpl<Type> &types) {
354 for (const auto &field : getElements())
355 types.push_back(field.type);
358 uint64_t StructType::getMaxFieldID() const {
359 uint64_t fieldID = 0;
360 for (const auto &field : getElements())
361 fieldID += 1 + hw::FieldIdImpl::getMaxFieldID(field.type);
365 std::pair<Type, uint64_t>
366 StructType::getSubTypeByFieldID(uint64_t fieldID) const {
369 auto [maxId, fieldIDs] = getFieldIDsStruct(*this);
370 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
371 auto subfieldIndex = std::distance(fieldIDs.begin(), it);
372 auto subfieldType = getElements()[subfieldIndex].type;
373 auto subfieldID = fieldID - fieldIDs[subfieldIndex];
374 return {subfieldType, subfieldID};
377 std::pair<uint64_t, bool>
378 StructType::projectToChildFieldID(uint64_t fieldID, uint64_t index) const {
379 auto [maxId, fieldIDs] = getFieldIDsStruct(*this);
380 auto childRoot = fieldIDs[index];
382 index + 1 >= getElements().size() ? maxId : (fieldIDs[index + 1] - 1);
383 return std::make_pair(fieldID - childRoot,
384 fieldID >= childRoot && fieldID <= rangeEnd);
387 uint64_t StructType::getFieldID(uint64_t index) const {
388 auto [maxId, fieldIDs] = getFieldIDsStruct(*this);
389 return fieldIDs[index];
392 uint64_t StructType::getIndexForFieldID(uint64_t fieldID) const {
393 assert(!getElements().empty() && "Bundle must have >0 fields");
394 auto [maxId, fieldIDs] = getFieldIDsStruct(*this);
395 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
396 return std::distance(fieldIDs.begin(), it);
399 std::pair<uint64_t, uint64_t>
400 StructType::getIndexAndSubfieldID(uint64_t fieldID) const {
401 auto index = getIndexForFieldID(fieldID);
402 auto elementFieldID = getFieldID(index);
403 return {index, fieldID - elementFieldID};
406 //===----------------------------------------------------------------------===//
408 //===----------------------------------------------------------------------===//
413 bool operator==(const OffsetFieldInfo &a, const OffsetFieldInfo &b) {
414 return a.name == b.name && a.type == b.type && a.offset == b.offset;
417 llvm::hash_code hash_value(const OffsetFieldInfo &fi) {
418 return llvm::hash_combine(fi.name, fi.type, fi.offset);
420 } // namespace detail
424 Type UnionType::parse(AsmParser &p) {
425 llvm::SmallVector<FieldInfo, 4> parameters;
426 llvm::StringSet<> nameSet;
427 bool hasDuplicateName = false;
428 if (p.parseCommaSeparatedList(
429 mlir::AsmParser::Delimiter::LessGreater, [&]() -> ParseResult {
433 auto fieldLoc = p.getCurrentLocation();
434 if (p.parseKeyword(&name) || p.parseColon() || p.parseType(type))
437 if (!nameSet.insert(name).second) {
438 p.emitError(fieldLoc, "duplicate field name \'" + name +
439 "\' in hw.union type");
440 // Continue parsing to print all duplicates, but make sure to
442 hasDuplicateName = true;
446 if (succeeded(p.parseOptionalKeyword("offset")))
447 if (p.parseInteger(offset))
449 parameters.push_back(UnionType::FieldInfo{
450 StringAttr::get(p.getContext(), name), type, offset});
455 if (hasDuplicateName)
458 return get(p.getContext(), parameters);
461 void UnionType::print(AsmPrinter &odsPrinter) const {
463 llvm::interleaveComma(
464 getElements(), odsPrinter, [&](const UnionType::FieldInfo &field) {
465 odsPrinter << field.name.getValue() << ": " << field.type;
467 odsPrinter << " offset " << field.offset;
472 LogicalResult UnionType::verify(function_ref<InFlightDiagnostic()> emitError,
473 ArrayRef<UnionType::FieldInfo> elements) {
474 llvm::SmallDenseSet<StringAttr> fieldNameSet;
475 LogicalResult result = success();
476 fieldNameSet.reserve(elements.size());
477 for (const auto &elt : elements)
478 if (!fieldNameSet.insert(elt.name).second) {
480 emitError() << "duplicate field name '" << elt.name.getValue()
481 << "' in hw.union type";
486 std::optional<uint32_t> UnionType::getFieldIndex(mlir::StringAttr fieldName) {
487 ArrayRef<hw::UnionType::FieldInfo> elems = getElements();
488 for (size_t idx = 0, numElems = elems.size(); idx < numElems; ++idx)
489 if (elems[idx].name == fieldName)
494 std::optional<uint32_t> UnionType::getFieldIndex(mlir::StringRef fieldName) {
495 return getFieldIndex(StringAttr::get(getContext(), fieldName));
498 UnionType::FieldInfo UnionType::getFieldInfo(::mlir::StringRef fieldName) {
499 if (auto fieldIndex = getFieldIndex(fieldName))
500 return getElements()[*fieldIndex];
504 Type UnionType::getFieldType(mlir::StringRef fieldName) {
505 return getFieldInfo(fieldName).type;
508 //===----------------------------------------------------------------------===//
510 //===----------------------------------------------------------------------===//
512 Type EnumType::parse(AsmParser &p) {
513 llvm::SmallVector<Attribute> fields;
515 if (p.parseCommaSeparatedList(AsmParser::Delimiter::LessGreater, [&]() {
517 if (p.parseKeyword(&name))
519 fields.push_back(StringAttr::get(p.getContext(), name));
524 return get(p.getContext(), ArrayAttr::get(p.getContext(), fields));
527 void EnumType::print(AsmPrinter &p) const {
529 llvm::interleaveComma(getFields(), p, [&](Attribute enumerator) {
530 p << llvm::cast<StringAttr>(enumerator).getValue();
535 bool EnumType::contains(mlir::StringRef field) {
536 return indexOf(field).has_value();
539 std::optional<size_t> EnumType::indexOf(mlir::StringRef field) {
540 for (auto it : llvm::enumerate(getFields()))
541 if (llvm::cast<StringAttr>(it.value()).getValue() == field)
546 size_t EnumType::getBitWidth() {
547 auto w = getFields().size();
549 return llvm::Log2_64_Ceil(getFields().size());
553 //===----------------------------------------------------------------------===//
555 //===----------------------------------------------------------------------===//
557 static ParseResult parseHWArray(AsmParser &p, Attribute &dim, Type &inner) {
559 auto int64Type = p.getBuilder().getIntegerType(64);
561 if (auto res = p.parseOptionalInteger(dimLiteral); res.has_value())
562 dim = p.getBuilder().getI64IntegerAttr(dimLiteral);
563 else if (!p.parseOptionalAttribute(dim, int64Type).has_value())
566 if (!isa<IntegerAttr, ParamExprAttr, ParamDeclRefAttr>(dim)) {
567 p.emitError(p.getNameLoc(), "unsupported dimension kind in hw.array");
571 if (p.parseXInDimensionList() || parseHWElementType(p, inner))
577 static void printHWArray(AsmPrinter &p, Attribute dim, Type elementType) {
578 p.printAttributeWithoutType(dim);
580 printHWElementType(p, elementType);
583 size_t ArrayType::getNumElements() const {
584 if (auto intAttr = llvm::dyn_cast<IntegerAttr>(getSizeAttr()))
585 return intAttr.getInt();
589 LogicalResult ArrayType::verify(function_ref<InFlightDiagnostic()> emitError,
590 Type innerType, Attribute size) {
591 if (hasHWInOutType(innerType))
592 return emitError() << "hw.array cannot contain InOut types";
596 uint64_t ArrayType::getMaxFieldID() const {
597 return getNumElements() *
598 (hw::FieldIdImpl::getMaxFieldID(getElementType()) + 1);
601 std::pair<Type, uint64_t>
602 ArrayType::getSubTypeByFieldID(uint64_t fieldID) const {
605 return {getElementType(), getIndexAndSubfieldID(fieldID).second};
608 std::pair<uint64_t, bool>
609 ArrayType::projectToChildFieldID(uint64_t fieldID, uint64_t index) const {
610 auto childRoot = getFieldID(index);
612 index >= getNumElements() ? getMaxFieldID() : (getFieldID(index + 1) - 1);
613 return std::make_pair(fieldID - childRoot,
614 fieldID >= childRoot && fieldID <= rangeEnd);
617 uint64_t ArrayType::getIndexForFieldID(uint64_t fieldID) const {
618 assert(fieldID && "fieldID must be at least 1");
619 // Divide the field ID by the number of fieldID's per element.
623 std::pair<uint64_t, uint64_t>
627 return {index, fieldID - elementFieldID};
642 return emitError() <<
"invalid element for uarray type";
646 size_t UnpackedArrayType::getNumElements()
const {
647 if (
auto intAttr = llvm::dyn_cast<IntegerAttr>(getSizeAttr()))
648 return intAttr.getInt();
653 return getNumElements() *
657 std::pair<Type, uint64_t>
664 std::pair<uint64_t, bool>
666 uint64_t index)
const {
670 return std::make_pair(fieldID - childRoot,
671 fieldID >= childRoot && fieldID <= rangeEnd);
675 assert(fieldID &&
"fieldID must be at least 1");
680 std::pair<uint64_t, uint64_t>
684 return {index, fieldID - elementFieldID};
698 return emitError() <<
"invalid element for hw.inout type " <<
innerType;
707 return llvm::TypeSwitch<Type, Type>(type)
708 .Case([](TypeAliasType t) {
711 .Case([](ArrayType t) {
715 .Case([](UnpackedArrayType t) {
719 .Case([](StructType t) {
720 SmallVector<StructType::FieldInfo> fieldInfo;
721 for (
auto field : t.getElements())
722 fieldInfo.push_back(StructType::FieldInfo{
726 .Default([](Type t) {
return t; });
733 Type TypeAliasType::parse(AsmParser &p) {
736 if (p.parseLess() || p.parseAttribute(ref) || p.parseComma() ||
737 p.parseType(type) || p.parseGreater())
740 return get(ref, type);
743 void TypeAliasType::print(AsmPrinter &p)
const {
744 p <<
"<" << getRef() <<
", " << getInnerType() <<
">";
749 TypedeclOp TypeAliasType::getTypeDecl(
const HWSymbolCache &cache) {
750 SymbolRefAttr ref = getRef();
751 auto typeScope = ::dyn_cast_or_null<TypeScopeOp>(
756 return typeScope.lookupSymbol<TypedeclOp>(ref.getLeafReference());
764 ArrayRef<ModulePort> ports) {
765 if (llvm::any_of(ports, [](
const ModulePort &port) {
768 return emitError() <<
"Ports cannot be inout types";
772 size_t ModuleType::getPortIdForInputId(
size_t idx) {
773 assert(idx < getImpl()->inputToAbs.size() &&
"input port out of range");
774 return getImpl()->inputToAbs[idx];
777 size_t ModuleType::getPortIdForOutputId(
size_t idx) {
778 assert(idx < getImpl()->outputToAbs.size() &&
" output port out of range");
779 return getImpl()->outputToAbs[idx];
782 size_t ModuleType::getInputIdForPortId(
size_t idx) {
783 auto nIdx = getImpl()->absToInput[idx];
788 size_t ModuleType::getOutputIdForPortId(
size_t idx) {
789 auto nIdx = getImpl()->absToOutput[idx];
794 size_t ModuleType::getNumInputs() {
return getImpl()->inputToAbs.size(); }
796 size_t ModuleType::getNumOutputs() {
return getImpl()->outputToAbs.size(); }
800 SmallVector<Type> ModuleType::getInputTypes() {
801 SmallVector<Type> retval;
802 for (
auto &p : getPorts()) {
804 retval.push_back(p.type);
812 SmallVector<Type> ModuleType::getOutputTypes() {
813 SmallVector<Type> retval;
814 for (
auto &p : getPorts())
816 retval.push_back(p.type);
820 SmallVector<Type> ModuleType::getPortTypes() {
821 SmallVector<Type> retval;
822 for (
auto &p : getPorts())
823 retval.push_back(p.type);
827 Type ModuleType::getInputType(
size_t idx) {
828 const auto &portInfo = getPorts()[getPortIdForInputId(idx)];
830 return portInfo.type;
834 Type ModuleType::getOutputType(
size_t idx) {
835 return getPorts()[getPortIdForOutputId(idx)].type;
838 SmallVector<Attribute> ModuleType::getInputNames() {
839 SmallVector<Attribute> retval;
840 for (
auto &p : getPorts())
842 retval.push_back(p.name);
846 SmallVector<Attribute> ModuleType::getOutputNames() {
847 SmallVector<Attribute> retval;
848 for (
auto &p : getPorts())
850 retval.push_back(p.name);
854 StringAttr ModuleType::getPortNameAttr(
size_t idx) {
855 return getPorts()[idx].name;
858 StringRef ModuleType::getPortName(
size_t idx) {
859 auto sa = getPortNameAttr(idx);
861 return sa.getValue();
865 StringAttr ModuleType::getInputNameAttr(
size_t idx) {
866 return getPorts()[getPortIdForInputId(idx)].name;
869 StringRef ModuleType::getInputName(
size_t idx) {
870 auto sa = getInputNameAttr(idx);
872 return sa.getValue();
876 StringAttr ModuleType::getOutputNameAttr(
size_t idx) {
877 return getPorts()[getPortIdForOutputId(idx)].name;
880 StringRef ModuleType::getOutputName(
size_t idx) {
881 auto sa = getOutputNameAttr(idx);
883 return sa.getValue();
887 bool ModuleType::isOutput(
size_t idx) {
888 auto &p = getPorts()[idx];
892 FunctionType ModuleType::getFuncType() {
893 SmallVector<Type> inputs, outputs;
894 for (
auto p : getPorts())
896 inputs.push_back(p.type);
900 outputs.push_back(p.type);
904 ArrayRef<ModulePort> ModuleType::getPorts()
const {
905 return getImpl()->getPorts();
911 SmallVector<ModulePort, 8> resolvedPorts;
913 FailureOr<Type> resolvedType =
915 if (failed(resolvedType))
917 port.type = *resolvedType;
918 resolvedPorts.push_back(port);
941 llvm::report_fatal_error(
"invalid direction");
947 SmallVectorImpl<ModulePort> &ports) {
948 return p.parseCommaSeparatedList(
949 mlir::AsmParser::Delimiter::LessGreater, [&]() -> ParseResult {
953 if (p.parseKeyword(&dir) || p.parseKeywordOrString(&name) ||
954 p.parseColon() || p.parseType(type))
963 static void printPorts(AsmPrinter &p, ArrayRef<ModulePort> ports) {
965 llvm::interleaveComma(ports, p, [&](
const ModulePort &port) {
967 p.printKeywordOrString(port.
name.getValue());
968 p <<
" : " << port.
type;
973 Type ModuleType::parse(AsmParser &odsParser) {
974 llvm::SmallVector<ModulePort, 4> ports;
977 return get(odsParser.getContext(), ports);
980 void ModuleType::print(AsmPrinter &odsPrinter)
const {
985 ArrayRef<Attribute> inputNames,
986 ArrayRef<Attribute> outputNames) {
988 cast<FunctionType>(cast<mlir::FunctionOpInterface>(op).getFunctionType()),
989 inputNames, outputNames);
993 ArrayRef<Attribute> inputNames,
994 ArrayRef<Attribute> outputNames) {
995 SmallVector<ModulePort> ports;
996 if (!inputNames.empty()) {
997 for (
auto [t, n] : llvm::zip_equal(fnty.getInputs(), inputNames))
998 if (
auto iot = dyn_cast<hw::InOutType>(t))
999 ports.push_back({cast<StringAttr>(n), iot.getElementType(),
1004 for (
auto t : fnty.getInputs())
1005 if (
auto iot = dyn_cast<hw::InOutType>(t))
1011 if (!outputNames.empty()) {
1012 for (
auto [t, n] : llvm::zip_equal(fnty.getResults(), outputNames))
1015 for (
auto t : fnty.getResults())
1021 detail::ModuleTypeStorage::ModuleTypeStorage(ArrayRef<ModulePort> inPorts)
1023 size_t nextInput = 0;
1024 size_t nextOutput = 0;
1025 for (
auto [idx, p] : llvm::enumerate(
ports)) {
1044 void HWDialect::registerTypes() {
1046 #define GET_TYPEDEF_LIST
1047 #include "circt/Dialect/HW/HWTypes.cpp.inc"
assert(baseType &&"element must be base type")
static ModulePort::Direction strToDir(StringRef str)
static void printPorts(AsmPrinter &p, ArrayRef< ModulePort > ports)
Print out a list of named fields surrounded by <>.
static StringRef dirToStr(ModulePort::Direction dir)
static ParseResult parseHWArray(AsmParser &parser, Attribute &dim, Type &elementType)
static ParseResult parseHWElementType(AsmParser &parser, Type &elementType)
Parse and print nested HW types nicely.
static ParseResult parsePorts(AsmParser &p, SmallVectorImpl< ModulePort > &ports)
Parse a list of field names and types within <>.
static void printHWArray(AsmPrinter &printer, Attribute dim, Type elementType)
static Type computeCanonicalType(Type type)
static void printHWElementType(AsmPrinter &printer, Type dim)
static unsigned getIndexForFieldID(BundleType type, unsigned fieldID)
static unsigned getMaxFieldID(FIRRTLBaseType type)
This stores lookup tables to make manipulating and working with the IR more efficient.
mlir::Operation * getDefinition(mlir::Attribute attr) const override
Lookup a definition for 'symbol' in the cache.
static LogicalResult verify(Value clock, bool eventExists, mlir::Location loc)
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
uint64_t getWidth(Type t)
mlir::Type innerType(mlir::Type type)
size_t getNumPorts(Operation *op)
Return the number of ports in a module-like thing (modules, memories, etc)
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 getMaxFieldID(Type)
ModuleType fnToMod(Operation *op, ArrayRef< Attribute > inputNames, ArrayRef< Attribute > outputNames)
LogicalResult resolveParametricTypes(Location loc, ArrayAttr parameters, ArrayRef< Type > types, SmallVectorImpl< Type > &resolvedTypes, const EmitErrorFn &emitError)
Stores a resolved version of each type in.
bool isHWIntegerType(mlir::Type type)
Return true if the specified type is a value HW Integer type.
bool isHWValueType(mlir::Type type)
Return true if the specified type can be used as an HW value type, that is the set of types that can ...
enum PEO uint32_t mlir::FailureOr< mlir::Type > evaluateParametricType(mlir::Location loc, mlir::ArrayAttr parameters, mlir::Type type, bool emitErrors=true)
Returns a resolved version of 'type' wherein any parameter reference has been evaluated based on the ...
int64_t getBitWidth(mlir::Type type)
Return the hardware bit width of a type.
bool isHWEnumType(mlir::Type type)
Return true if the specified type is a HW Enum type.
mlir::Type getCanonicalType(mlir::Type type)
bool hasHWInOutType(mlir::Type type)
Return true if the specified type contains known marker types like InOutType.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
SmallVector< ModulePort > ports
The parametric data held by the storage class.
SmallVector< size_t > absToInput
SmallVector< size_t > outputToAbs
SmallVector< size_t > inputToAbs
SmallVector< size_t > absToOutput