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"
35static 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);
204Type IntType::get(mlir::TypedAttr width) {
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))
212 return IntegerType::get(width.getContext(),
213 cstWidth.getValue().getZExtValue());
215 return Base::get(width.getContext(), width);
218Type 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())
228void IntType::print(AsmPrinter &p)
const {
230 p.printAttributeWithoutType(
getWidth());
245 return llvm::hash_combine(fi.
name, fi.
type);
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 +
"\'");
271 hasDuplicateName = true;
274 parameters.push_back(
275 FieldInfo{StringAttr::get(p.getContext(), name), type});
279 if (hasDuplicateName)
285static 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;
294Type StructType::parse(AsmParser &p) {
295 llvm::SmallVector<FieldInfo, 4> parameters;
298 return get(p.getContext(), parameters);
301LogicalResult 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";
315void StructType::print(AsmPrinter &p)
const {
printFields(p, getElements()); }
317Type StructType::getFieldType(mlir::StringRef fieldName) {
318 for (
const auto &field : getElements())
319 if (field.name == fieldName)
324std::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)
332std::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)
340static std::pair<uint64_t, SmallVector<uint64_t>>
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);
353 return {fieldID, fieldIDs};
356void StructType::getInnerTypes(SmallVectorImpl<Type> &types) {
357 for (
const auto &field : getElements())
358 types.push_back(field.type);
361uint64_t StructType::getMaxFieldID()
const {
362 uint64_t fieldID = 0;
363 for (
const auto &field : getElements())
368std::pair<Type, uint64_t>
369StructType::getSubTypeByFieldID(uint64_t fieldID)
const {
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};
380std::pair<uint64_t, bool>
381StructType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
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);
390uint64_t StructType::getFieldID(uint64_t index)
const {
392 return fieldIDs[index];
395uint64_t StructType::getIndexForFieldID(uint64_t fieldID)
const {
396 assert(!getElements().
empty() &&
"Bundle must have >0 fields");
398 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
399 return std::distance(fieldIDs.begin(), it);
402std::pair<uint64_t, uint64_t>
403StructType::getIndexAndSubfieldID(uint64_t fieldID)
const {
406 return {index, fieldID - elementFieldID};
409std::optional<DenseMap<Attribute, Type>>
410hw::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});
418Type hw::StructType::getTypeAtIndex(Attribute index)
const {
419 auto indexAttr = llvm::dyn_cast<IntegerAttr>(index);
444Type 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");
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);
481void 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;
492LogicalResult 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";
506std::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)
514std::optional<uint32_t> UnionType::getFieldIndex(mlir::StringRef fieldName) {
515 return getFieldIndex(StringAttr::get(getContext(), fieldName));
518UnionType::FieldInfo UnionType::getFieldInfo(::mlir::StringRef fieldName) {
519 if (
auto fieldIndex = getFieldIndex(fieldName))
520 return getElements()[*fieldIndex];
524Type UnionType::getFieldType(mlir::StringRef fieldName) {
525 return getFieldInfo(fieldName).type;
532Type 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));
547void EnumType::print(AsmPrinter &p)
const {
549 llvm::interleaveComma(getFields(), p, [&](Attribute enumerator) {
550 p << llvm::cast<StringAttr>(enumerator).getValue();
555bool EnumType::contains(mlir::StringRef field) {
556 return indexOf(field).has_value();
559std::optional<size_t> EnumType::indexOf(mlir::StringRef field) {
560 for (
auto it :
llvm::enumerate(getFields()))
561 if (
llvm::cast<StringAttr>(it.value()).getValue() == field)
566size_t EnumType::getBitWidth() {
567 auto w = getFields().size();
569 return llvm::Log2_64_Ceil(getFields().size());
577static 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");
604 p.printAttributeWithoutType(dim);
609size_t ArrayType::getNumElements()
const {
610 if (
auto intAttr = llvm::dyn_cast<IntegerAttr>(getSizeAttr()))
611 return intAttr.getInt();
615LogicalResult ArrayType::verify(function_ref<InFlightDiagnostic()> emitError,
616 Type innerType, Attribute size) {
618 return emitError() <<
"hw.array cannot contain InOut types";
622uint64_t ArrayType::getMaxFieldID()
const {
623 return getNumElements() *
627std::pair<Type, uint64_t>
628ArrayType::getSubTypeByFieldID(uint64_t fieldID)
const {
634std::pair<uint64_t, bool>
635ArrayType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
639 return std::make_pair(fieldID - childRoot,
640 fieldID >= childRoot && fieldID <= rangeEnd);
643uint64_t ArrayType::getIndexForFieldID(uint64_t fieldID)
const {
644 assert(fieldID &&
"fieldID must be at least 1");
649std::pair<uint64_t, uint64_t>
650ArrayType::getIndexAndSubfieldID(uint64_t fieldID)
const {
653 return {index, fieldID - elementFieldID};
656uint64_t ArrayType::getFieldID(uint64_t index)
const {
660std::optional<DenseMap<Attribute, Type>>
661hw::ArrayType::getSubelementIndexMap()
const {
662 DenseMap<Attribute, Type> destructured;
663 for (
unsigned i = 0; i < getNumElements(); ++i)
665 {IntegerAttr::get(IndexType::get(getContext()), i), getElementType()});
669Type hw::ArrayType::getTypeAtIndex(Attribute index)
const {
670 return getElementType();
678UnpackedArrayType::verify(function_ref<InFlightDiagnostic()> emitError,
679 Type innerType, Attribute size) {
681 return emitError() <<
"invalid element for uarray type";
685size_t UnpackedArrayType::getNumElements()
const {
686 if (
auto intAttr = llvm::dyn_cast<IntegerAttr>(getSizeAttr()))
687 return intAttr.getInt();
691uint64_t UnpackedArrayType::getMaxFieldID()
const {
692 return getNumElements() *
696std::pair<Type, uint64_t>
697UnpackedArrayType::getSubTypeByFieldID(uint64_t fieldID)
const {
703std::pair<uint64_t, bool>
704UnpackedArrayType::projectToChildFieldID(uint64_t fieldID,
705 uint64_t index)
const {
709 return std::make_pair(fieldID - childRoot,
710 fieldID >= childRoot && fieldID <= rangeEnd);
713uint64_t UnpackedArrayType::getIndexForFieldID(uint64_t fieldID)
const {
714 assert(fieldID &&
"fieldID must be at least 1");
719std::pair<uint64_t, uint64_t>
720UnpackedArrayType::getIndexAndSubfieldID(uint64_t fieldID)
const {
723 return {index, fieldID - elementFieldID};
726uint64_t UnpackedArrayType::getFieldID(uint64_t index)
const {
734LogicalResult InOutType::verify(function_ref<InFlightDiagnostic()> emitError,
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{
763 return StructType::get(t.getContext(), fieldInfo);
765 .Default([](Type t) {
return t; });
768TypeAliasType TypeAliasType::get(SymbolRefAttr ref, Type innerType) {
772Type TypeAliasType::parse(AsmParser &p) {
775 if (p.parseLess() || p.parseAttribute(ref) || p.parseComma() ||
776 p.parseType(type) || p.parseGreater())
779 return get(ref, type);
782void TypeAliasType::print(AsmPrinter &p)
const {
783 p <<
"<" << getRef() <<
", " << getInnerType() <<
">";
788TypedeclOp TypeAliasType::getTypeDecl(
const HWSymbolCache &cache) {
789 SymbolRefAttr ref = getRef();
790 auto typeScope = ::dyn_cast_or_null<TypeScopeOp>(
795 return typeScope.lookupSymbol<TypedeclOp>(ref.getLeafReference());
802LogicalResult ModuleType::verify(function_ref<InFlightDiagnostic()> emitError,
803 ArrayRef<ModulePort> ports) {
804 if (llvm::any_of(ports, [](
const ModulePort &port) {
807 return emitError() <<
"Ports cannot be inout types";
811size_t ModuleType::getPortIdForInputId(
size_t idx) {
812 assert(idx < getImpl()->inputToAbs.size() &&
"input port out of range");
813 return getImpl()->inputToAbs[idx];
816size_t ModuleType::getPortIdForOutputId(
size_t idx) {
817 assert(idx < getImpl()->outputToAbs.size() &&
" output port out of range");
818 return getImpl()->outputToAbs[idx];
821size_t ModuleType::getInputIdForPortId(
size_t idx) {
822 auto nIdx = getImpl()->absToInput[idx];
827size_t ModuleType::getOutputIdForPortId(
size_t idx) {
828 auto nIdx = getImpl()->absToOutput[idx];
833size_t ModuleType::getNumInputs() {
return getImpl()->inputToAbs.size(); }
835size_t ModuleType::getNumOutputs() {
return getImpl()->outputToAbs.size(); }
837size_t ModuleType::getNumPorts() {
return getPorts().size(); }
839SmallVector<Type> ModuleType::getInputTypes() {
840 SmallVector<Type> retval;
841 for (
auto &p : getPorts()) {
842 if (p.dir == ModulePort::Direction::Input)
843 retval.push_back(p.type);
844 else if (p.dir == ModulePort::Direction::InOut) {
845 retval.push_back(hw::InOutType::get(p.type));
851SmallVector<Type> ModuleType::getOutputTypes() {
852 SmallVector<Type> retval;
853 for (
auto &p : getPorts())
855 retval.push_back(p.type);
859SmallVector<Type> ModuleType::getPortTypes() {
860 SmallVector<Type> retval;
861 for (
auto &p : getPorts())
862 retval.push_back(p.type);
866Type ModuleType::getInputType(
size_t idx) {
867 const auto &portInfo = getPorts()[getPortIdForInputId(idx)];
869 return portInfo.type;
870 return InOutType::get(portInfo.type);
873Type ModuleType::getOutputType(
size_t idx) {
874 return getPorts()[getPortIdForOutputId(idx)].type;
877SmallVector<Attribute> ModuleType::getInputNames() {
878 SmallVector<Attribute> retval;
879 for (
auto &p : getPorts())
881 retval.push_back(p.name);
885SmallVector<Attribute> ModuleType::getOutputNames() {
886 SmallVector<Attribute> retval;
887 for (
auto &p : getPorts())
889 retval.push_back(p.name);
893StringAttr ModuleType::getPortNameAttr(
size_t idx) {
894 return getPorts()[idx].name;
897StringRef ModuleType::getPortName(
size_t idx) {
898 auto sa = getPortNameAttr(idx);
900 return sa.getValue();
904StringAttr ModuleType::getInputNameAttr(
size_t idx) {
905 return getPorts()[getPortIdForInputId(idx)].name;
908StringRef ModuleType::getInputName(
size_t idx) {
909 auto sa = getInputNameAttr(idx);
911 return sa.getValue();
915StringAttr ModuleType::getOutputNameAttr(
size_t idx) {
916 return getPorts()[getPortIdForOutputId(idx)].name;
919StringRef ModuleType::getOutputName(
size_t idx) {
920 auto sa = getOutputNameAttr(idx);
922 return sa.getValue();
926bool ModuleType::isOutput(
size_t idx) {
927 auto &p = getPorts()[idx];
928 return p.dir == ModulePort::Direction::Output;
931FunctionType ModuleType::getFuncType() {
932 SmallVector<Type> inputs, outputs;
933 for (
auto p : getPorts())
935 inputs.push_back(p.type);
937 inputs.push_back(InOutType::get(p.type));
939 outputs.push_back(p.type);
940 return FunctionType::get(getContext(), inputs, outputs);
943ArrayRef<ModulePort> ModuleType::getPorts()
const {
944 return getImpl()->getPorts();
947FailureOr<ModuleType> ModuleType::resolveParametricTypes(ArrayAttr parameters,
950 SmallVector<ModulePort, 8> resolvedPorts;
952 FailureOr<Type> resolvedType =
954 if (failed(resolvedType))
956 port.type = *resolvedType;
957 resolvedPorts.push_back(port);
959 return ModuleType::get(getContext(), resolvedPorts);
964 case ModulePort::Direction::Input:
966 case ModulePort::Direction::Output:
968 case ModulePort::Direction::InOut:
975 return ModulePort::Direction::Input;
977 return ModulePort::Direction::Output;
979 return ModulePort::Direction::InOut;
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))
996 {StringAttr::get(p.getContext(), name), type,
strToDir(dir)});
1002static 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;
1012Type ModuleType::parse(AsmParser &odsParser) {
1013 llvm::SmallVector<ModulePort, 4> ports;
1016 return get(odsParser.getContext(), ports);
1019void 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(),
1039 ModulePort::Direction::InOut});
1041 ports.push_back({cast<StringAttr>(n), t, ModulePort::Direction::Input});
1043 for (
auto t : fnty.getInputs())
1044 if (auto iot = dyn_cast<
hw::InOutType>(t))
1046 {{}, iot.getElementType(), ModulePort::Direction::InOut});
1048 ports.push_back({{}, t, ModulePort::Direction::Input});
1050 if (!outputNames.empty()) {
1051 for (
auto [t, n] :
llvm::zip_equal(fnty.getResults(), outputNames))
1052 ports.push_back({cast<StringAttr>(n), t, ModulePort::Direction::Output});
1054 for (
auto t : fnty.getResults())
1055 ports.push_back({{}, t, ModulePort::Direction::Output});
1057 return ModuleType::get(fnty.getContext(), ports);
1062 size_t nextInput = 0;
1063 size_t nextOutput = 0;
1064 for (
auto [idx, p] : llvm::enumerate(
ports)) {
1083void 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 void printFields(AsmPrinter &p, ArrayRef< FieldInfo > fields)
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 std::pair< uint64_t, SmallVector< uint64_t > > getFieldIDsStruct(const StructType &st)
static ParseResult parseFields(AsmParser &p, SmallVectorImpl< FieldInfo > ¶meters)
Parse a list of unique field names and types within <>.
static Type computeCanonicalType(Type type)
static void printHWElementType(AsmPrinter &printer, Type dim)
static unsigned getFieldID(BundleType type, unsigned index)
static unsigned getIndexForFieldID(BundleType type, unsigned fieldID)
static unsigned getMaxFieldID(FIRRTLBaseType type)
static InstancePath empty
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.
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Direction
The direction of a Component or Cell port.
uint64_t getWidth(Type t)
mlir::Type innerType(mlir::Type type)
std::pair< uint64_t, uint64_t > getIndexAndSubfieldID(Type type, uint64_t fieldID)
std::pair<::mlir::Type, uint64_t > getSubTypeByFieldID(Type, uint64_t fieldID)
uint64_t getMaxFieldID(Type)
llvm::hash_code hash_value(const FieldInfo &fi)
bool operator==(const FieldInfo &a, const FieldInfo &b)
ModuleType fnToMod(Operation *op, ArrayRef< Attribute > inputNames, ArrayRef< Attribute > outputNames)
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 ...
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.
Struct defining a field. Used in structs.
SmallVector< ModulePort > ports
The parametric data held by the storage class.
ModuleTypeStorage(ArrayRef< ModulePort > inPorts)
SmallVector< size_t > absToInput
SmallVector< size_t > outputToAbs
SmallVector< size_t > inputToAbs
SmallVector< size_t > absToOutput
Struct defining a field with an offset. Used in unions.