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 "mlir/Interfaces/MemorySlotInterfaces.h"
26 #include "llvm/ADT/SmallSet.h"
27 #include "llvm/ADT/StringExtras.h"
28 #include "llvm/ADT/StringSet.h"
29 #include "llvm/ADT/TypeSwitch.h"
31 using namespace circt;
35 static ParseResult
parseHWArray(AsmParser &parser, Attribute &dim,
42 #define GET_TYPEDEF_CLASSES
43 #include "circt/Dialect/HW/HWTypes.cpp.inc"
51 if (
auto typeAlias = dyn_cast<TypeAliasType>(type))
52 canonicalType = typeAlias.getCanonicalType();
63 if (isa<hw::IntType>(canonicalType))
66 auto intType = dyn_cast<IntegerType>(canonicalType);
67 if (!intType || !intType.isSignless())
82 if (isa<IntegerType, IntType, EnumType>(type))
85 if (
auto array = dyn_cast<ArrayType>(type))
88 if (
auto array = dyn_cast<UnpackedArrayType>(type))
91 if (
auto t = dyn_cast<StructType>(type))
92 return llvm::all_of(t.getElements(),
93 [](
auto f) { return isHWValueType(f.type); });
95 if (
auto t = dyn_cast<UnionType>(type))
96 return llvm::all_of(t.getElements(),
97 [](
auto f) { return isHWValueType(f.type); });
99 if (
auto t = dyn_cast<TypeAliasType>(type))
111 return llvm::TypeSwitch<::mlir::Type, size_t>(type)
113 [](IntegerType t) {
return t.getIntOrFloatBitWidth(); })
114 .Case<ArrayType, UnpackedArrayType>([](
auto a) {
115 int64_t elementBitWidth =
getBitWidth(a.getElementType());
116 if (elementBitWidth < 0)
117 return elementBitWidth;
118 int64_t dimBitWidth = a.getNumElements();
120 return static_cast<int64_t
>(-1L);
121 return (int64_t)a.getNumElements() * elementBitWidth;
123 .Case<StructType>([](StructType s) {
125 for (
auto field : s.getElements()) {
133 .Case<UnionType>([](UnionType u) {
135 for (
auto field : u.getElements()) {
136 int64_t fieldSize =
getBitWidth(field.type) + field.offset;
137 if (fieldSize > maxSize)
142 .Case<EnumType>([](EnumType e) {
return e.getBitWidth(); })
143 .Case<TypeAliasType>(
144 [](TypeAliasType t) {
return getBitWidth(t.getCanonicalType()); })
145 .Default([](Type) {
return -1; });
152 if (
auto array = dyn_cast<ArrayType>(type))
155 if (
auto array = dyn_cast<UnpackedArrayType>(type))
158 if (
auto t = dyn_cast<StructType>(type)) {
159 return std::any_of(t.getElements().begin(), t.getElements().end(),
160 [](
const auto &f) { return hasHWInOutType(f.type); });
163 if (
auto t = dyn_cast<TypeAliasType>(type))
166 return isa<InOutType>(type);
175 auto fullString =
static_cast<DialectAsmParser &
>(p).getFullSymbolSpec();
176 auto *curPtr = p.getCurrentLocation().getPointer();
178 StringRef(curPtr, fullString.size() - (curPtr - fullString.data()));
180 if (typeString.starts_with(
"array<") || typeString.starts_with(
"inout<") ||
181 typeString.starts_with(
"uarray<") || typeString.starts_with(
"struct<") ||
182 typeString.starts_with(
"typealias<") || typeString.starts_with(
"int<") ||
183 typeString.starts_with(
"enum<")) {
184 llvm::StringRef mnemonic;
185 if (
auto parseResult = generatedTypeParser(p, &mnemonic, result);
186 parseResult.has_value())
188 return p.emitError(p.getNameLoc(),
"invalid type `") << typeString <<
"`";
191 return p.parseType(result);
195 if (succeeded(generatedTypePrinter(element, p)))
197 p.printType(element);
206 auto widthWidth = llvm::dyn_cast<IntegerType>(width.getType());
207 assert(widthWidth && widthWidth.getWidth() == 32 &&
208 "!hw.int width must be 32-bits");
211 if (
auto cstWidth = llvm::dyn_cast<IntegerAttr>(width))
213 cstWidth.getValue().getZExtValue());
215 return Base::get(width.getContext(), width);
218 Type IntType::parse(AsmParser &p) {
220 auto int32Type = p.getBuilder().getIntegerType(32);
222 mlir::TypedAttr width;
223 if (p.parseLess() || p.parseAttribute(width, int32Type) || p.parseGreater())
228 void IntType::print(AsmPrinter &p)
const {
230 p.printAttributeWithoutType(
getWidth());
234 //===----------------------------------------------------------------------===//
236 //===----------------------------------------------------------------------===//
241 bool operator==(const FieldInfo &a, const FieldInfo &b) {
242 return a.name == b.name && a.type == b.type;
244 llvm::hash_code hash_value(const FieldInfo &fi) {
245 return llvm::hash_combine(fi.name, fi.type);
247 } // namespace detail
253 static ParseResult parseFields(AsmParser &p,
254 SmallVectorImpl<FieldInfo> ¶meters) {
255 llvm::StringSet<> nameSet;
256 bool hasDuplicateName = false;
257 auto parseResult = p.parseCommaSeparatedList(
258 mlir::AsmParser::Delimiter::LessGreater, [&]() -> ParseResult {
262 auto fieldLoc = p.getCurrentLocation();
263 if (p.parseKeywordOrString(&name) || p.parseColon() ||
267 if (!nameSet.insert(name).second) {
268 p.emitError(fieldLoc, "duplicate field name \'" + name + "\'");
269 // Continue parsing to print all duplicates, but make sure to error
271 hasDuplicateName = true;
274 parameters.push_back(
275 FieldInfo{StringAttr::get(p.getContext(), name), type});
279 if (hasDuplicateName)
285 static void printFields(AsmPrinter &p, ArrayRef<FieldInfo> fields) {
287 llvm::interleaveComma(fields, p, [&](const FieldInfo &field) {
288 p.printKeywordOrString(field.name.getValue());
289 p << ": " << field.type;
294 Type StructType::parse(AsmParser &p) {
295 llvm::SmallVector<FieldInfo, 4> parameters;
296 if (parseFields(p, parameters))
298 return get(p.getContext(), parameters);
301 LogicalResult StructType::verify(function_ref<InFlightDiagnostic()> emitError,
302 ArrayRef<StructType::FieldInfo> elements) {
303 llvm::SmallDenseSet<StringAttr> fieldNameSet;
304 LogicalResult result = success();
305 fieldNameSet.reserve(elements.size());
306 for (const auto &elt : elements)
307 if (!fieldNameSet.insert(elt.name).second) {
309 emitError() << "duplicate field name '" << elt.name.getValue()
310 << "' in hw.struct type";
315 void StructType::print(AsmPrinter &p) const { printFields(p, getElements()); }
317 Type StructType::getFieldType(mlir::StringRef fieldName) {
318 for (const auto &field : getElements())
319 if (field.name == fieldName)
324 std::optional<uint32_t> StructType::getFieldIndex(mlir::StringRef fieldName) {
325 ArrayRef<hw::StructType::FieldInfo> elems = getElements();
326 for (size_t idx = 0, numElems = elems.size(); idx < numElems; ++idx)
327 if (elems[idx].name == fieldName)
332 std::optional<uint32_t> StructType::getFieldIndex(mlir::StringAttr fieldName) {
333 ArrayRef<hw::StructType::FieldInfo> elems = getElements();
334 for (size_t idx = 0, numElems = elems.size(); idx < numElems; ++idx)
335 if (elems[idx].name == fieldName)
340 static std::pair<uint64_t, SmallVector<uint64_t>>
341 getFieldIDsStruct(const StructType &st) {
342 uint64_t fieldID = 0;
343 auto elements = st.getElements();
344 SmallVector<uint64_t> fieldIDs;
345 fieldIDs.reserve(elements.size());
346 for (auto &element : elements) {
347 auto type = element.type;
349 fieldIDs.push_back(fieldID);
350 // Increment the field ID for the next field by the number of subfields.
351 fieldID += hw::FieldIdImpl::getMaxFieldID(type);
353 return {fieldID, fieldIDs};
356 void StructType::getInnerTypes(SmallVectorImpl<Type> &types) {
357 for (const auto &field : getElements())
358 types.push_back(field.type);
361 uint64_t StructType::getMaxFieldID() const {
362 uint64_t fieldID = 0;
363 for (const auto &field : getElements())
364 fieldID += 1 + hw::FieldIdImpl::getMaxFieldID(field.type);
368 std::pair<Type, uint64_t>
369 StructType::getSubTypeByFieldID(uint64_t fieldID) const {
372 auto [maxId, fieldIDs] = getFieldIDsStruct(*this);
373 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
374 auto subfieldIndex = std::distance(fieldIDs.begin(), it);
375 auto subfieldType = getElements()[subfieldIndex].type;
376 auto subfieldID = fieldID - fieldIDs[subfieldIndex];
377 return {subfieldType, subfieldID};
380 std::pair<uint64_t, bool>
381 StructType::projectToChildFieldID(uint64_t fieldID, uint64_t index) const {
382 auto [maxId, fieldIDs] = getFieldIDsStruct(*this);
383 auto childRoot = fieldIDs[index];
385 index + 1 >= getElements().size() ? maxId : (fieldIDs[index + 1] - 1);
386 return std::make_pair(fieldID - childRoot,
387 fieldID >= childRoot && fieldID <= rangeEnd);
390 uint64_t StructType::getFieldID(uint64_t index) const {
391 auto [maxId, fieldIDs] = getFieldIDsStruct(*this);
392 return fieldIDs[index];
395 uint64_t StructType::getIndexForFieldID(uint64_t fieldID) const {
396 assert(!getElements().empty() && "Bundle must have >0 fields");
397 auto [maxId, fieldIDs] = getFieldIDsStruct(*this);
398 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
399 return std::distance(fieldIDs.begin(), it);
402 std::pair<uint64_t, uint64_t>
403 StructType::getIndexAndSubfieldID(uint64_t fieldID) const {
404 auto index = getIndexForFieldID(fieldID);
405 auto elementFieldID = getFieldID(index);
406 return {index, fieldID - elementFieldID};
409 std::optional<DenseMap<Attribute, Type>>
410 hw::StructType::getSubelementIndexMap() const {
411 DenseMap<Attribute, Type> destructured;
412 for (auto [i, field] : llvm::enumerate(getElements()))
414 {IntegerAttr::get(IndexType::get(getContext()), i), field.type});
418 Type hw::StructType::getTypeAtIndex(Attribute index) const {
419 auto indexAttr = llvm::dyn_cast<IntegerAttr>(index);
423 return getSubTypeByFieldID(indexAttr.getInt()).first;
426 //===----------------------------------------------------------------------===//
428 //===----------------------------------------------------------------------===//
433 bool operator==(const OffsetFieldInfo &a, const OffsetFieldInfo &b) {
434 return a.name == b.name && a.type == b.type && a.offset == b.offset;
437 llvm::hash_code hash_value(const OffsetFieldInfo &fi) {
438 return llvm::hash_combine(fi.name, fi.type, fi.offset);
440 } // namespace detail
444 Type UnionType::parse(AsmParser &p) {
445 llvm::SmallVector<FieldInfo, 4> parameters;
446 llvm::StringSet<> nameSet;
447 bool hasDuplicateName = false;
448 if (p.parseCommaSeparatedList(
449 mlir::AsmParser::Delimiter::LessGreater, [&]() -> ParseResult {
453 auto fieldLoc = p.getCurrentLocation();
454 if (p.parseKeyword(&name) || p.parseColon() || p.parseType(type))
457 if (!nameSet.insert(name).second) {
458 p.emitError(fieldLoc, "duplicate field name \'" + name +
459 "\' in hw.union type");
460 // Continue parsing to print all duplicates, but make sure to
462 hasDuplicateName = true;
466 if (succeeded(p.parseOptionalKeyword("offset")))
467 if (p.parseInteger(offset))
469 parameters.push_back(UnionType::FieldInfo{
470 StringAttr::get(p.getContext(), name), type, offset});
475 if (hasDuplicateName)
478 return get(p.getContext(), parameters);
481 void UnionType::print(AsmPrinter &odsPrinter) const {
483 llvm::interleaveComma(
484 getElements(), odsPrinter, [&](const UnionType::FieldInfo &field) {
485 odsPrinter << field.name.getValue() << ": " << field.type;
487 odsPrinter << " offset " << field.offset;
492 LogicalResult UnionType::verify(function_ref<InFlightDiagnostic()> emitError,
493 ArrayRef<UnionType::FieldInfo> elements) {
494 llvm::SmallDenseSet<StringAttr> fieldNameSet;
495 LogicalResult result = success();
496 fieldNameSet.reserve(elements.size());
497 for (const auto &elt : elements)
498 if (!fieldNameSet.insert(elt.name).second) {
500 emitError() << "duplicate field name '" << elt.name.getValue()
501 << "' in hw.union type";
506 std::optional<uint32_t> UnionType::getFieldIndex(mlir::StringAttr fieldName) {
507 ArrayRef<hw::UnionType::FieldInfo> elems = getElements();
508 for (size_t idx = 0, numElems = elems.size(); idx < numElems; ++idx)
509 if (elems[idx].name == fieldName)
514 std::optional<uint32_t> UnionType::getFieldIndex(mlir::StringRef fieldName) {
515 return getFieldIndex(StringAttr::get(getContext(), fieldName));
518 UnionType::FieldInfo UnionType::getFieldInfo(::mlir::StringRef fieldName) {
519 if (auto fieldIndex = getFieldIndex(fieldName))
520 return getElements()[*fieldIndex];
524 Type UnionType::getFieldType(mlir::StringRef fieldName) {
525 return getFieldInfo(fieldName).type;
528 //===----------------------------------------------------------------------===//
530 //===----------------------------------------------------------------------===//
532 Type EnumType::parse(AsmParser &p) {
533 llvm::SmallVector<Attribute> fields;
535 if (p.parseCommaSeparatedList(AsmParser::Delimiter::LessGreater, [&]() {
537 if (p.parseKeyword(&name))
539 fields.push_back(StringAttr::get(p.getContext(), name));
544 return get(p.getContext(), ArrayAttr::get(p.getContext(), fields));
547 void EnumType::print(AsmPrinter &p) const {
549 llvm::interleaveComma(getFields(), p, [&](Attribute enumerator) {
550 p << llvm::cast<StringAttr>(enumerator).getValue();
555 bool EnumType::contains(mlir::StringRef field) {
556 return indexOf(field).has_value();
559 std::optional<size_t> EnumType::indexOf(mlir::StringRef field) {
560 for (auto it : llvm::enumerate(getFields()))
561 if (llvm::cast<StringAttr>(it.value()).getValue() == field)
566 size_t EnumType::getBitWidth() {
567 auto w = getFields().size();
569 return llvm::Log2_64_Ceil(getFields().size());
573 //===----------------------------------------------------------------------===//
575 //===----------------------------------------------------------------------===//
577 static ParseResult parseHWArray(AsmParser &p, Attribute &dim, Type &inner) {
579 auto int64Type = p.getBuilder().getIntegerType(64);
581 if (auto res = p.parseOptionalInteger(dimLiteral); res.has_value()) {
584 dim = p.getBuilder().getI64IntegerAttr(dimLiteral);
585 } else if (auto res64 = p.parseOptionalAttribute(dim, int64Type);
590 return p.emitError(p.getNameLoc(), "expected integer");
592 if (!isa<IntegerAttr, ParamExprAttr, ParamDeclRefAttr>(dim)) {
593 p.emitError(p.getNameLoc(), "unsupported dimension kind in hw.array");
597 if (p.parseXInDimensionList() || parseHWElementType(p, inner))
603 static void printHWArray(AsmPrinter &p, Attribute dim, Type elementType) {
604 p.printAttributeWithoutType(dim);
606 printHWElementType(p, elementType);
609 size_t ArrayType::getNumElements() const {
610 if (auto intAttr = llvm::dyn_cast<IntegerAttr>(getSizeAttr()))
611 return intAttr.getInt();
615 LogicalResult ArrayType::verify(function_ref<InFlightDiagnostic()> emitError,
616 Type innerType, Attribute size) {
617 if (hasHWInOutType(innerType))
618 return emitError() << "hw.array cannot contain InOut types";
622 uint64_t ArrayType::getMaxFieldID() const {
623 return getNumElements() *
624 (hw::FieldIdImpl::getMaxFieldID(getElementType()) + 1);
627 std::pair<Type, uint64_t>
628 ArrayType::getSubTypeByFieldID(uint64_t fieldID) const {
631 return {getElementType(), getIndexAndSubfieldID(fieldID).second};
634 std::pair<uint64_t, bool>
635 ArrayType::projectToChildFieldID(uint64_t fieldID, uint64_t index) const {
636 auto childRoot = getFieldID(index);
638 index >= getNumElements() ? getMaxFieldID() : (getFieldID(index + 1) - 1);
639 return std::make_pair(fieldID - childRoot,
640 fieldID >= childRoot && fieldID <= rangeEnd);
643 uint64_t ArrayType::getIndexForFieldID(uint64_t fieldID) const {
644 assert(fieldID && "fieldID must be at least 1");
645 // Divide the field ID by the number of fieldID's per element.
649 std::pair<uint64_t, uint64_t>
653 return {index, fieldID - elementFieldID};
660 std::optional<DenseMap<Attribute, Type>>
661 hw::ArrayType::getSubelementIndexMap()
const {
662 DenseMap<Attribute, Type> destructured;
663 for (
unsigned i = 0; i < getNumElements(); ++i)
669 Type hw::ArrayType::getTypeAtIndex(Attribute index)
const {
670 return getElementType();
681 return emitError() <<
"invalid element for uarray type";
685 size_t UnpackedArrayType::getNumElements()
const {
686 if (
auto intAttr = llvm::dyn_cast<IntegerAttr>(getSizeAttr()))
687 return intAttr.getInt();
692 return getNumElements() *
696 std::pair<Type, uint64_t>
703 std::pair<uint64_t, bool>
705 uint64_t index)
const {
709 return std::make_pair(fieldID - childRoot,
710 fieldID >= childRoot && fieldID <= rangeEnd);
714 assert(fieldID &&
"fieldID must be at least 1");
719 std::pair<uint64_t, uint64_t>
723 return {index, fieldID - elementFieldID};
737 return emitError() <<
"invalid element for hw.inout type " <<
innerType;
746 return llvm::TypeSwitch<Type, Type>(type)
747 .Case([](TypeAliasType t) {
750 .Case([](ArrayType t) {
754 .Case([](UnpackedArrayType t) {
758 .Case([](StructType t) {
759 SmallVector<StructType::FieldInfo> fieldInfo;
760 for (
auto field : t.getElements())
761 fieldInfo.push_back(StructType::FieldInfo{
765 .Default([](Type t) {
return t; });
772 Type TypeAliasType::parse(AsmParser &p) {
775 if (p.parseLess() || p.parseAttribute(ref) || p.parseComma() ||
776 p.parseType(type) || p.parseGreater())
779 return get(ref, type);
782 void TypeAliasType::print(AsmPrinter &p)
const {
783 p <<
"<" << getRef() <<
", " << getInnerType() <<
">";
788 TypedeclOp TypeAliasType::getTypeDecl(
const HWSymbolCache &cache) {
789 SymbolRefAttr ref = getRef();
790 auto typeScope = ::dyn_cast_or_null<TypeScopeOp>(
795 return typeScope.lookupSymbol<TypedeclOp>(ref.getLeafReference());
803 ArrayRef<ModulePort> ports) {
804 if (llvm::any_of(ports, [](
const ModulePort &port) {
807 return emitError() <<
"Ports cannot be inout types";
811 size_t ModuleType::getPortIdForInputId(
size_t idx) {
812 assert(idx < getImpl()->inputToAbs.size() &&
"input port out of range");
813 return getImpl()->inputToAbs[idx];
816 size_t ModuleType::getPortIdForOutputId(
size_t idx) {
817 assert(idx < getImpl()->outputToAbs.size() &&
" output port out of range");
818 return getImpl()->outputToAbs[idx];
821 size_t ModuleType::getInputIdForPortId(
size_t idx) {
822 auto nIdx = getImpl()->absToInput[idx];
827 size_t ModuleType::getOutputIdForPortId(
size_t idx) {
828 auto nIdx = getImpl()->absToOutput[idx];
833 size_t ModuleType::getNumInputs() {
return getImpl()->inputToAbs.size(); }
835 size_t ModuleType::getNumOutputs() {
return getImpl()->outputToAbs.size(); }
839 SmallVector<Type> ModuleType::getInputTypes() {
840 SmallVector<Type> retval;
841 for (
auto &p : getPorts()) {
843 retval.push_back(p.type);
851 SmallVector<Type> ModuleType::getOutputTypes() {
852 SmallVector<Type> retval;
853 for (
auto &p : getPorts())
855 retval.push_back(p.type);
859 SmallVector<Type> ModuleType::getPortTypes() {
860 SmallVector<Type> retval;
861 for (
auto &p : getPorts())
862 retval.push_back(p.type);
866 Type ModuleType::getInputType(
size_t idx) {
867 const auto &portInfo = getPorts()[getPortIdForInputId(idx)];
869 return portInfo.type;
873 Type ModuleType::getOutputType(
size_t idx) {
874 return getPorts()[getPortIdForOutputId(idx)].type;
877 SmallVector<Attribute> ModuleType::getInputNames() {
878 SmallVector<Attribute> retval;
879 for (
auto &p : getPorts())
881 retval.push_back(p.name);
885 SmallVector<Attribute> ModuleType::getOutputNames() {
886 SmallVector<Attribute> retval;
887 for (
auto &p : getPorts())
889 retval.push_back(p.name);
893 StringAttr ModuleType::getPortNameAttr(
size_t idx) {
894 return getPorts()[idx].name;
897 StringRef ModuleType::getPortName(
size_t idx) {
898 auto sa = getPortNameAttr(idx);
900 return sa.getValue();
904 StringAttr ModuleType::getInputNameAttr(
size_t idx) {
905 return getPorts()[getPortIdForInputId(idx)].name;
908 StringRef ModuleType::getInputName(
size_t idx) {
909 auto sa = getInputNameAttr(idx);
911 return sa.getValue();
915 StringAttr ModuleType::getOutputNameAttr(
size_t idx) {
916 return getPorts()[getPortIdForOutputId(idx)].name;
919 StringRef ModuleType::getOutputName(
size_t idx) {
920 auto sa = getOutputNameAttr(idx);
922 return sa.getValue();
926 bool ModuleType::isOutput(
size_t idx) {
927 auto &p = getPorts()[idx];
931 FunctionType ModuleType::getFuncType() {
932 SmallVector<Type> inputs, outputs;
933 for (
auto p : getPorts())
935 inputs.push_back(p.type);
939 outputs.push_back(p.type);
943 ArrayRef<ModulePort> ModuleType::getPorts()
const {
944 return getImpl()->getPorts();
950 SmallVector<ModulePort, 8> resolvedPorts;
952 FailureOr<Type> resolvedType =
954 if (failed(resolvedType))
956 port.type = *resolvedType;
957 resolvedPorts.push_back(port);
980 llvm::report_fatal_error(
"invalid direction");
986 SmallVectorImpl<ModulePort> &ports) {
987 return p.parseCommaSeparatedList(
988 mlir::AsmParser::Delimiter::LessGreater, [&]() -> ParseResult {
992 if (p.parseKeyword(&dir) || p.parseKeywordOrString(&name) ||
993 p.parseColon() || p.parseType(type))
1002 static void printPorts(AsmPrinter &p, ArrayRef<ModulePort> ports) {
1004 llvm::interleaveComma(ports, p, [&](
const ModulePort &port) {
1006 p.printKeywordOrString(port.
name.getValue());
1007 p <<
" : " << port.
type;
1012 Type ModuleType::parse(AsmParser &odsParser) {
1013 llvm::SmallVector<ModulePort, 4> ports;
1016 return get(odsParser.getContext(), ports);
1019 void ModuleType::print(AsmPrinter &odsPrinter)
const {
1024 ArrayRef<Attribute> inputNames,
1025 ArrayRef<Attribute> outputNames) {
1027 cast<FunctionType>(cast<mlir::FunctionOpInterface>(op).getFunctionType()),
1028 inputNames, outputNames);
1032 ArrayRef<Attribute> inputNames,
1033 ArrayRef<Attribute> outputNames) {
1034 SmallVector<ModulePort> ports;
1035 if (!inputNames.empty()) {
1036 for (
auto [t, n] : llvm::zip_equal(fnty.getInputs(), inputNames))
1037 if (
auto iot = dyn_cast<hw::InOutType>(t))
1038 ports.push_back({cast<StringAttr>(n), iot.getElementType(),
1043 for (
auto t : fnty.getInputs())
1044 if (
auto iot = dyn_cast<hw::InOutType>(t))
1050 if (!outputNames.empty()) {
1051 for (
auto [t, n] : llvm::zip_equal(fnty.getResults(), outputNames))
1054 for (
auto t : fnty.getResults())
1060 detail::ModuleTypeStorage::ModuleTypeStorage(ArrayRef<ModulePort> inPorts)
1062 size_t nextInput = 0;
1063 size_t nextOutput = 0;
1064 for (
auto [idx, p] : llvm::enumerate(
ports)) {
1083 void HWDialect::registerTypes() {
1085 #define GET_TYPEDEF_LIST
1086 #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