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))
113 return llvm::TypeSwitch<::mlir::Type, int64_t>(type)
115 [](IntegerType t) {
return t.getIntOrFloatBitWidth(); })
116 .Default([](Type type) -> int64_t {
118 if (
auto iface = dyn_cast<BitWidthTypeInterface>(type)) {
119 std::optional<int64_t> width = iface.getBitWidth();
120 return width.has_value() ? *width : -1;
130 if (
auto array = dyn_cast<ArrayType>(type))
133 if (
auto array = dyn_cast<UnpackedArrayType>(type))
136 if (
auto t = dyn_cast<StructType>(type)) {
137 return std::any_of(t.getElements().begin(), t.getElements().end(),
138 [](
const auto &f) { return hasHWInOutType(f.type); });
141 if (
auto t = dyn_cast<TypeAliasType>(type))
144 return isa<InOutType>(type);
153 auto fullString =
static_cast<DialectAsmParser &
>(p).getFullSymbolSpec();
154 auto *curPtr = p.getCurrentLocation().getPointer();
156 StringRef(curPtr, fullString.size() - (curPtr - fullString.data()));
158 if (typeString.starts_with(
"array<") || typeString.starts_with(
"inout<") ||
159 typeString.starts_with(
"uarray<") || typeString.starts_with(
"struct<") ||
160 typeString.starts_with(
"typealias<") || typeString.starts_with(
"int<") ||
161 typeString.starts_with(
"enum<") || typeString.starts_with(
"union<")) {
162 llvm::StringRef mnemonic;
163 if (
auto parseResult = generatedTypeParser(p, &mnemonic, result);
164 parseResult.has_value())
166 return p.emitError(p.getNameLoc(),
"invalid type `") << typeString <<
"`";
169 return p.parseType(result);
173 if (succeeded(generatedTypePrinter(element, p)))
175 p.printType(element);
182Type IntType::get(mlir::TypedAttr width) {
184 auto widthWidth = llvm::dyn_cast<IntegerType>(width.getType());
185 assert(widthWidth && widthWidth.getWidth() == 32 &&
186 "!hw.int width must be 32-bits");
189 if (
auto cstWidth = llvm::dyn_cast<IntegerAttr>(width))
190 return IntegerType::get(width.getContext(),
191 cstWidth.getValue().getZExtValue());
193 return Base::get(width.getContext(), width);
196Type IntType::parse(AsmParser &p) {
198 auto int32Type = p.getBuilder().getIntegerType(32);
200 mlir::TypedAttr width;
201 if (p.parseLess() || p.parseAttribute(width, int32Type) || p.parseGreater())
206void IntType::print(AsmPrinter &p)
const {
208 p.printAttributeWithoutType(
getWidth());
223 return llvm::hash_combine(fi.
name, fi.
type);
232 SmallVectorImpl<FieldInfo> ¶meters) {
233 llvm::StringSet<> nameSet;
234 bool hasDuplicateName =
false;
235 auto parseResult = p.parseCommaSeparatedList(
236 mlir::AsmParser::Delimiter::LessGreater, [&]() -> ParseResult {
240 auto fieldLoc = p.getCurrentLocation();
241 if (p.parseKeywordOrString(&name) || p.parseColon() ||
245 if (!nameSet.insert(name).second) {
246 p.emitError(fieldLoc,
"duplicate field name \'" + name +
"\'");
249 hasDuplicateName = true;
252 parameters.push_back(
253 FieldInfo{StringAttr::get(p.getContext(), name), type});
257 if (hasDuplicateName)
263static void printFields(AsmPrinter &p, ArrayRef<FieldInfo> fields) {
265 llvm::interleaveComma(fields, p, [&](
const FieldInfo &field) {
266 p.printKeywordOrString(field.
name.getValue());
267 p <<
": " << field.
type;
272Type StructType::parse(AsmParser &p) {
273 llvm::SmallVector<FieldInfo, 4> parameters;
276 return get(p.getContext(), parameters);
279LogicalResult StructType::verify(function_ref<InFlightDiagnostic()> emitError,
280 ArrayRef<StructType::FieldInfo> elements) {
281 llvm::SmallDenseSet<StringAttr> fieldNameSet;
282 LogicalResult result = success();
283 fieldNameSet.reserve(elements.size());
284 for (
const auto &elt : elements)
285 if (!fieldNameSet.insert(elt.name).second) {
287 emitError() <<
"duplicate field name '" << elt.name.getValue()
288 <<
"' in hw.struct type";
293void StructType::print(AsmPrinter &p)
const {
printFields(p, getElements()); }
295Type StructType::getFieldType(mlir::StringRef fieldName) {
296 for (
const auto &field : getElements())
297 if (field.name == fieldName)
302std::optional<uint32_t> StructType::getFieldIndex(mlir::StringRef fieldName) {
303 ArrayRef<hw::StructType::FieldInfo> elems = getElements();
304 for (
size_t idx = 0, numElems = elems.size(); idx < numElems; ++idx)
305 if (elems[idx].name == fieldName)
310std::optional<uint32_t> StructType::getFieldIndex(mlir::StringAttr fieldName) {
311 ArrayRef<hw::StructType::FieldInfo> elems = getElements();
312 for (
size_t idx = 0, numElems = elems.size(); idx < numElems; ++idx)
313 if (elems[idx].name == fieldName)
318static std::pair<uint64_t, SmallVector<uint64_t>>
320 uint64_t fieldID = 0;
321 auto elements = st.getElements();
322 SmallVector<uint64_t> fieldIDs;
323 fieldIDs.reserve(elements.size());
324 for (
auto &element : elements) {
325 auto type = element.type;
327 fieldIDs.push_back(fieldID);
331 return {fieldID, fieldIDs};
334void StructType::getInnerTypes(SmallVectorImpl<Type> &types) {
335 for (
const auto &field : getElements())
336 types.push_back(field.type);
339uint64_t StructType::getMaxFieldID()
const {
340 uint64_t fieldID = 0;
341 for (
const auto &field : getElements())
346std::pair<Type, uint64_t>
347StructType::getSubTypeByFieldID(uint64_t fieldID)
const {
351 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
352 auto subfieldIndex = std::distance(fieldIDs.begin(), it);
353 auto subfieldType = getElements()[subfieldIndex].type;
354 auto subfieldID = fieldID - fieldIDs[subfieldIndex];
355 return {subfieldType, subfieldID};
358std::pair<uint64_t, bool>
359StructType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
361 auto childRoot = fieldIDs[index];
363 index + 1 >= getElements().size() ? maxId : (fieldIDs[index + 1] - 1);
364 return std::make_pair(fieldID - childRoot,
365 fieldID >= childRoot && fieldID <= rangeEnd);
368uint64_t StructType::getFieldID(uint64_t index)
const {
370 return fieldIDs[index];
373uint64_t StructType::getIndexForFieldID(uint64_t fieldID)
const {
374 assert(!getElements().
empty() &&
"Bundle must have >0 fields");
376 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
377 return std::distance(fieldIDs.begin(), it);
380std::pair<uint64_t, uint64_t>
381StructType::getIndexAndSubfieldID(uint64_t fieldID)
const {
384 return {index, fieldID - elementFieldID};
387std::optional<DenseMap<Attribute, Type>>
388hw::StructType::getSubelementIndexMap()
const {
389 DenseMap<Attribute, Type> destructured;
390 for (
auto [i, field] :
llvm::enumerate(getElements()))
392 {IntegerAttr::get(IndexType::get(getContext()), i), field.type});
396Type hw::StructType::getTypeAtIndex(Attribute index)
const {
397 auto indexAttr = llvm::dyn_cast<IntegerAttr>(index);
404std::optional<int64_t> StructType::getBitWidth()
const {
406 for (
auto field : getElements()) {
407 int64_t fieldSize = hw::getBitWidth(field.type);
433Type UnionType::parse(AsmParser &p) {
434 llvm::SmallVector<FieldInfo, 4> parameters;
435 llvm::StringSet<> nameSet;
436 bool hasDuplicateName =
false;
437 if (p.parseCommaSeparatedList(
438 mlir::AsmParser::Delimiter::LessGreater, [&]() -> ParseResult {
442 auto fieldLoc = p.getCurrentLocation();
443 if (p.parseKeyword(&name) || p.parseColon() || p.parseType(type))
446 if (!nameSet.insert(name).second) {
447 p.emitError(fieldLoc,
"duplicate field name \'" + name +
448 "\' in hw.union type");
451 hasDuplicateName = true;
455 if (succeeded(p.parseOptionalKeyword(
"offset")))
456 if (p.parseInteger(offset))
458 parameters.push_back(UnionType::FieldInfo{
459 StringAttr::get(p.getContext(), name), type, offset});
464 if (hasDuplicateName)
467 return get(p.getContext(), parameters);
470void UnionType::print(AsmPrinter &odsPrinter)
const {
472 llvm::interleaveComma(
473 getElements(), odsPrinter, [&](
const UnionType::FieldInfo &field) {
474 odsPrinter << field.name.getValue() <<
": " << field.type;
476 odsPrinter <<
" offset " << field.offset;
481LogicalResult UnionType::verify(function_ref<InFlightDiagnostic()> emitError,
482 ArrayRef<UnionType::FieldInfo> elements) {
483 llvm::SmallDenseSet<StringAttr> fieldNameSet;
484 LogicalResult result = success();
485 fieldNameSet.reserve(elements.size());
486 for (
const auto &elt : elements)
487 if (!fieldNameSet.insert(elt.name).second) {
489 emitError() <<
"duplicate field name '" << elt.name.getValue()
490 <<
"' in hw.union type";
495std::optional<uint32_t> UnionType::getFieldIndex(mlir::StringAttr fieldName) {
496 ArrayRef<hw::UnionType::FieldInfo> elems = getElements();
497 for (
size_t idx = 0, numElems = elems.size(); idx < numElems; ++idx)
498 if (elems[idx].name == fieldName)
503std::optional<uint32_t> UnionType::getFieldIndex(mlir::StringRef fieldName) {
504 return getFieldIndex(StringAttr::get(getContext(), fieldName));
507UnionType::FieldInfo UnionType::getFieldInfo(::mlir::StringRef fieldName) {
508 if (
auto fieldIndex = getFieldIndex(fieldName))
509 return getElements()[*fieldIndex];
513Type UnionType::getFieldType(mlir::StringRef fieldName) {
514 return getFieldInfo(fieldName).type;
517std::optional<int64_t> UnionType::getBitWidth()
const {
519 for (
auto field : getElements()) {
520 int64_t fieldSize = hw::getBitWidth(field.type);
523 fieldSize += field.offset;
524 if (fieldSize > maxSize)
534Type EnumType::parse(AsmParser &p) {
535 llvm::SmallVector<Attribute> fields;
537 if (p.parseCommaSeparatedList(AsmParser::Delimiter::LessGreater, [&]() {
539 if (p.parseKeyword(&name))
541 fields.push_back(StringAttr::get(p.getContext(), name));
546 return get(p.getContext(), ArrayAttr::get(p.getContext(), fields));
549void EnumType::print(AsmPrinter &p)
const {
551 llvm::interleaveComma(getFields(), p, [&](Attribute enumerator) {
552 p << llvm::cast<StringAttr>(enumerator).getValue();
557bool EnumType::contains(mlir::StringRef field) {
558 return indexOf(field).has_value();
561std::optional<size_t> EnumType::indexOf(mlir::StringRef field) {
562 for (
auto it :
llvm::enumerate(getFields()))
563 if (
llvm::cast<StringAttr>(it.value()).getValue() == field)
568std::optional<int64_t> EnumType::getBitWidth()
const {
569 auto w = getFields().size();
571 return llvm::Log2_64_Ceil(w);
579static ParseResult
parseHWArray(AsmParser &p, Attribute &dim, Type &inner) {
581 auto int64Type = p.getBuilder().getIntegerType(64);
583 if (
auto res = p.parseOptionalInteger(dimLiteral); res.has_value()) {
586 dim = p.getBuilder().getI64IntegerAttr(dimLiteral);
587 }
else if (
auto res64 = p.parseOptionalAttribute(dim, int64Type);
592 return p.emitError(p.getNameLoc(),
"expected integer");
594 if (!isa<IntegerAttr, ParamExprAttr, ParamDeclRefAttr>(dim)) {
595 p.emitError(p.getNameLoc(),
"unsupported dimension kind in hw.array");
606 p.printAttributeWithoutType(dim);
611size_t ArrayType::getNumElements()
const {
612 if (
auto intAttr = llvm::dyn_cast<IntegerAttr>(getSizeAttr()))
613 return intAttr.getInt();
617LogicalResult ArrayType::verify(function_ref<InFlightDiagnostic()> emitError,
618 Type innerType, Attribute size) {
620 return emitError() <<
"hw.array cannot contain InOut types";
624uint64_t ArrayType::getMaxFieldID()
const {
625 return getNumElements() *
629std::pair<Type, uint64_t>
630ArrayType::getSubTypeByFieldID(uint64_t fieldID)
const {
636std::pair<uint64_t, bool>
637ArrayType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
641 return std::make_pair(fieldID - childRoot,
642 fieldID >= childRoot && fieldID <= rangeEnd);
645uint64_t ArrayType::getIndexForFieldID(uint64_t fieldID)
const {
646 assert(fieldID &&
"fieldID must be at least 1");
651std::pair<uint64_t, uint64_t>
652ArrayType::getIndexAndSubfieldID(uint64_t fieldID)
const {
655 return {index, fieldID - elementFieldID};
658uint64_t ArrayType::getFieldID(uint64_t index)
const {
662std::optional<DenseMap<Attribute, Type>>
663hw::ArrayType::getSubelementIndexMap()
const {
664 DenseMap<Attribute, Type> destructured;
665 for (
unsigned i = 0; i < getNumElements(); ++i)
667 {IntegerAttr::get(IndexType::get(getContext()), i), getElementType()});
671Type hw::ArrayType::getTypeAtIndex(Attribute index)
const {
672 return getElementType();
675std::optional<int64_t> hw::ArrayType::getBitWidth()
const {
676 auto elementBitWidth = hw::getBitWidth(getElementType());
677 if (elementBitWidth < 0)
690UnpackedArrayType::verify(function_ref<InFlightDiagnostic()> emitError,
691 Type innerType, Attribute size) {
693 return emitError() <<
"invalid element for uarray type";
697size_t UnpackedArrayType::getNumElements()
const {
698 if (
auto intAttr = llvm::dyn_cast<IntegerAttr>(getSizeAttr()))
699 return intAttr.getInt();
703uint64_t UnpackedArrayType::getMaxFieldID()
const {
704 return getNumElements() *
708std::pair<Type, uint64_t>
709UnpackedArrayType::getSubTypeByFieldID(uint64_t fieldID)
const {
715std::pair<uint64_t, bool>
716UnpackedArrayType::projectToChildFieldID(uint64_t fieldID,
717 uint64_t index)
const {
721 return std::make_pair(fieldID - childRoot,
722 fieldID >= childRoot && fieldID <= rangeEnd);
725uint64_t UnpackedArrayType::getIndexForFieldID(uint64_t fieldID)
const {
726 assert(fieldID &&
"fieldID must be at least 1");
731std::pair<uint64_t, uint64_t>
732UnpackedArrayType::getIndexAndSubfieldID(uint64_t fieldID)
const {
735 return {index, fieldID - elementFieldID};
738uint64_t UnpackedArrayType::getFieldID(uint64_t index)
const {
742std::optional<int64_t> UnpackedArrayType::getBitWidth()
const {
743 auto elementBitWidth = hw::getBitWidth(getElementType());
744 if (elementBitWidth < 0)
746 int64_t dimBitWidth = getNumElements();
749 return (int64_t)getNumElements() * elementBitWidth;
756LogicalResult InOutType::verify(function_ref<InFlightDiagnostic()> emitError,
759 return emitError() <<
"invalid element for hw.inout type " <<
innerType;
768 return llvm::TypeSwitch<Type, Type>(type)
769 .Case([](TypeAliasType t) {
772 .Case([](ArrayType t) {
776 .Case([](UnpackedArrayType t) {
780 .Case([](StructType t) {
781 SmallVector<StructType::FieldInfo> fieldInfo;
782 for (
auto field : t.getElements())
783 fieldInfo.push_back(StructType::FieldInfo{
785 return StructType::get(t.getContext(), fieldInfo);
787 .Default([](Type t) {
return t; });
790TypeAliasType TypeAliasType::get(SymbolRefAttr ref, Type innerType) {
794Type TypeAliasType::parse(AsmParser &p) {
797 if (p.parseLess() || p.parseAttribute(ref) || p.parseComma() ||
798 p.parseType(type) || p.parseGreater())
801 return get(ref, type);
804void TypeAliasType::print(AsmPrinter &p)
const {
805 p <<
"<" << getRef() <<
", " << getInnerType() <<
">";
810TypedeclOp TypeAliasType::getTypeDecl(
const HWSymbolCache &cache) {
811 SymbolRefAttr ref = getRef();
812 auto typeScope = ::dyn_cast_or_null<TypeScopeOp>(
817 return typeScope.lookupSymbol<TypedeclOp>(ref.getLeafReference());
820std::optional<int64_t> TypeAliasType::getBitWidth()
const {
831LogicalResult ModuleType::verify(function_ref<InFlightDiagnostic()> emitError,
832 ArrayRef<ModulePort> ports) {
833 if (llvm::any_of(ports, [](
const ModulePort &port) {
836 return emitError() <<
"Ports cannot be inout types";
840size_t ModuleType::getPortIdForInputId(
size_t idx) {
841 assert(idx < getImpl()->inputToAbs.size() &&
"input port out of range");
842 return getImpl()->inputToAbs[idx];
845size_t ModuleType::getPortIdForOutputId(
size_t idx) {
846 assert(idx < getImpl()->outputToAbs.size() &&
" output port out of range");
847 return getImpl()->outputToAbs[idx];
850size_t ModuleType::getInputIdForPortId(
size_t idx) {
851 auto nIdx = getImpl()->absToInput[idx];
856size_t ModuleType::getOutputIdForPortId(
size_t idx) {
857 auto nIdx = getImpl()->absToOutput[idx];
862size_t ModuleType::getNumInputs() {
return getImpl()->inputToAbs.size(); }
864size_t ModuleType::getNumOutputs() {
return getImpl()->outputToAbs.size(); }
866size_t ModuleType::getNumPorts() {
return getPorts().size(); }
868SmallVector<Type> ModuleType::getInputTypes() {
869 SmallVector<Type> retval;
870 for (
auto &p : getPorts()) {
871 if (p.dir == ModulePort::Direction::Input)
872 retval.push_back(p.type);
873 else if (p.dir == ModulePort::Direction::InOut) {
874 retval.push_back(hw::InOutType::get(p.type));
880SmallVector<Type> ModuleType::getOutputTypes() {
881 SmallVector<Type> retval;
882 for (
auto &p : getPorts())
884 retval.push_back(p.type);
888SmallVector<Type> ModuleType::getPortTypes() {
889 SmallVector<Type> retval;
890 for (
auto &p : getPorts())
891 retval.push_back(p.type);
895Type ModuleType::getInputType(
size_t idx) {
896 const auto &portInfo = getPorts()[getPortIdForInputId(idx)];
898 return portInfo.type;
899 return InOutType::get(portInfo.type);
902Type ModuleType::getOutputType(
size_t idx) {
903 return getPorts()[getPortIdForOutputId(idx)].type;
906SmallVector<Attribute> ModuleType::getInputNames() {
907 SmallVector<Attribute> retval;
908 for (
auto &p : getPorts())
910 retval.push_back(p.name);
914SmallVector<Attribute> ModuleType::getOutputNames() {
915 SmallVector<Attribute> retval;
916 for (
auto &p : getPorts())
918 retval.push_back(p.name);
922StringAttr ModuleType::getPortNameAttr(
size_t idx) {
923 return getPorts()[idx].name;
926StringRef ModuleType::getPortName(
size_t idx) {
927 auto sa = getPortNameAttr(idx);
929 return sa.getValue();
933StringAttr ModuleType::getInputNameAttr(
size_t idx) {
934 return getPorts()[getPortIdForInputId(idx)].name;
937StringRef ModuleType::getInputName(
size_t idx) {
938 auto sa = getInputNameAttr(idx);
940 return sa.getValue();
944StringAttr ModuleType::getOutputNameAttr(
size_t idx) {
945 return getPorts()[getPortIdForOutputId(idx)].name;
948StringRef ModuleType::getOutputName(
size_t idx) {
949 auto sa = getOutputNameAttr(idx);
951 return sa.getValue();
955bool ModuleType::isOutput(
size_t idx) {
956 auto &p = getPorts()[idx];
957 return p.dir == ModulePort::Direction::Output;
960FunctionType ModuleType::getFuncType() {
961 SmallVector<Type> inputs, outputs;
962 for (
auto p : getPorts())
964 inputs.push_back(p.type);
966 inputs.push_back(InOutType::get(p.type));
968 outputs.push_back(p.type);
969 return FunctionType::get(getContext(), inputs, outputs);
972ArrayRef<ModulePort> ModuleType::getPorts()
const {
973 return getImpl()->getPorts();
976FailureOr<ModuleType> ModuleType::resolveParametricTypes(ArrayAttr parameters,
979 SmallVector<ModulePort, 8> resolvedPorts;
981 FailureOr<Type> resolvedType =
983 if (failed(resolvedType))
985 port.type = *resolvedType;
986 resolvedPorts.push_back(port);
988 return ModuleType::get(getContext(), resolvedPorts);
993 case ModulePort::Direction::Input:
995 case ModulePort::Direction::Output:
997 case ModulePort::Direction::InOut:
1004 return ModulePort::Direction::Input;
1005 if (str ==
"output")
1006 return ModulePort::Direction::Output;
1008 return ModulePort::Direction::InOut;
1009 llvm::report_fatal_error(
"invalid direction");
1015 SmallVectorImpl<ModulePort> &ports) {
1016 return p.parseCommaSeparatedList(
1017 mlir::AsmParser::Delimiter::LessGreater, [&]() -> ParseResult {
1021 if (p.parseKeyword(&dir) || p.parseKeywordOrString(&name) ||
1022 p.parseColon() || p.parseType(type))
1025 {StringAttr::get(p.getContext(), name), type,
strToDir(dir)});
1031static void printPorts(AsmPrinter &p, ArrayRef<ModulePort> ports) {
1033 llvm::interleaveComma(ports, p, [&](
const ModulePort &port) {
1035 p.printKeywordOrString(port.
name.getValue());
1036 p <<
" : " << port.
type;
1041Type ModuleType::parse(AsmParser &odsParser) {
1042 llvm::SmallVector<ModulePort, 4> ports;
1045 return get(odsParser.getContext(), ports);
1048void ModuleType::print(AsmPrinter &odsPrinter)
const {
1053 ArrayRef<Attribute> inputNames,
1054 ArrayRef<Attribute> outputNames) {
1056 cast<FunctionType>(cast<mlir::FunctionOpInterface>(op).getFunctionType()),
1057 inputNames, outputNames);
1061 ArrayRef<Attribute> inputNames,
1062 ArrayRef<Attribute> outputNames) {
1063 SmallVector<ModulePort> ports;
1064 if (!inputNames.empty()) {
1065 for (
auto [t, n] : llvm::zip_equal(fnty.getInputs(), inputNames))
1066 if (
auto iot = dyn_cast<hw::InOutType>(t))
1067 ports.push_back({cast<StringAttr>(n), iot.getElementType(),
1068 ModulePort::Direction::InOut});
1070 ports.push_back({cast<StringAttr>(n), t, ModulePort::Direction::Input});
1072 for (
auto t : fnty.getInputs())
1073 if (auto iot = dyn_cast<
hw::InOutType>(t))
1075 {{}, iot.getElementType(), ModulePort::Direction::InOut});
1077 ports.push_back({{}, t, ModulePort::Direction::Input});
1079 if (!outputNames.empty()) {
1080 for (
auto [t, n] :
llvm::zip_equal(fnty.getResults(), outputNames))
1081 ports.push_back({cast<StringAttr>(n), t, ModulePort::Direction::Output});
1083 for (
auto t : fnty.getResults())
1084 ports.push_back({{}, t, ModulePort::Direction::Output});
1086 return ModuleType::get(fnty.getContext(), ports);
1091 size_t nextInput = 0;
1092 size_t nextOutput = 0;
1093 for (
auto [idx, p] : llvm::enumerate(
ports)) {
1112void HWDialect::registerTypes() {
1114#define GET_TYPEDEF_LIST
1115#include "circt/Dialect/HW/HWTypes.cpp.inc"
assert(baseType &&"element must be base type")
MlirType uint64_t numElements
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.