19#include "mlir/IR/AttrTypeSubElements.h"
20#include "mlir/IR/Builders.h"
21#include "mlir/IR/BuiltinTypes.h"
22#include "mlir/IR/Diagnostics.h"
23#include "mlir/IR/DialectImplementation.h"
24#include "mlir/IR/StorageUniquerSupport.h"
25#include "mlir/IR/Types.h"
26#include "mlir/Interfaces/MemorySlotInterfaces.h"
27#include "llvm/ADT/SmallSet.h"
28#include "llvm/ADT/StringExtras.h"
29#include "llvm/ADT/StringSet.h"
30#include "llvm/ADT/TypeSwitch.h"
31#include "llvm/Support/ErrorHandling.h"
37static ParseResult
parseHWArray(AsmParser &parser, Attribute &dim,
44#define GET_TYPEDEF_CLASSES
45#include "circt/Dialect/HW/HWTypes.cpp.inc"
52 mlir::AttrTypeReplacer replacer;
53 replacer.addReplacement(
54 [](TypeAliasType alias) {
return alias.getCanonicalType(); });
55 return replacer.replace(type);
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))
109 if (isa<IntegerType>(type))
125 return llvm::TypeSwitch<::mlir::Type, int64_t>(type)
127 [](IntegerType t) {
return t.getIntOrFloatBitWidth(); })
128 .Default([](Type type) -> int64_t {
130 if (
auto iface = dyn_cast<BitWidthTypeInterface>(type)) {
131 std::optional<int64_t> width = iface.getBitWidth();
132 return width.has_value() ? *width : -1;
142 if (
auto array = dyn_cast<ArrayType>(type))
145 if (
auto array = dyn_cast<UnpackedArrayType>(type))
148 if (
auto t = dyn_cast<StructType>(type)) {
149 return std::any_of(t.getElements().begin(), t.getElements().end(),
150 [](
const auto &f) { return hasHWInOutType(f.type); });
153 if (
auto t = dyn_cast<TypeAliasType>(type))
156 return isa<InOutType>(type);
160struct AggregateAttrFrame {
161 SmallVector<Attribute>
attrs;
162 SmallVector<Type> types;
165 AggregateAttrFrame(SmallVector<Type> &&types)
166 :
attrs(types.size()), types(std::move(types)), remaining(
attrs.size()) {}
168 void addChild(Attribute attr) {
attrs[--remaining] = attr; }
169 Type getNextChildType() {
return types[remaining - 1]; }
170 bool isFinished()
const {
return remaining == 0; }
180 auto *ctx = aggregateType.getContext();
181 SmallVector<AggregateAttrFrame> stack;
182 unsigned nextExtraction = 0;
184 auto pushToStack = [&](Type type) ->
bool {
185 return TypeSwitch<Type, bool>(type)
186 .Case<StructType>([&](
auto structType) {
187 auto len = structType.getElements().size();
188 SmallVector<Type> types;
190 for (
auto &element : structType.getElements())
192 stack.push_back(std::move(types));
195 .Case<ArrayType, UnpackedArrayType>([&](
auto arrayType) {
196 SmallVector<Type> types(arrayType.getNumElements(),
198 stack.push_back(std::move(types));
210 while (!stack.empty()) {
211 if (stack.back().isFinished()) {
212 auto frame = stack.pop_back_val();
213 result = ArrayAttr::get(ctx, frame.attrs);
215 stack.back().addChild(result);
219 auto curType = stack.back().getNextChildType();
220 if (
auto intType = dyn_cast<IntegerType>(curType)) {
221 auto width = intType.getWidth();
222 auto elemValue = width ? intVal.extractBits(width, nextExtraction)
223 : APInt(0, 0,
false);
224 nextExtraction += width;
225 stack.back().addChild(IntegerAttr::get(intType, elemValue));
227 if (!pushToStack(curType))
232 assert(nextExtraction == intVal.getBitWidth() &&
233 "constant wasn't fully processed");
243 SmallVector<Attribute> worklist;
244 worklist.push_back(attr);
246 assert(bitWidth >= 0 &&
"bit width must be known for constant");
247 result = APInt(bitWidth, 0);
248 unsigned nextInsertion = 0;
250 while (!worklist.empty()) {
251 auto current = worklist.pop_back_val();
252 if (
auto innerArray = dyn_cast<ArrayAttr>(current)) {
253 worklist.append(innerArray.begin(), innerArray.end());
257 if (
auto intAttr = dyn_cast<IntegerAttr>(current)) {
258 auto chunk = intAttr.getValue();
259 result.insertBits(chunk, nextInsertion);
260 nextInsertion += chunk.getBitWidth();
267 assert(nextInsertion == bitWidth &&
"constant wasn't fully processed");
277 auto fullString =
static_cast<DialectAsmParser &
>(p).getFullSymbolSpec();
278 auto *curPtr = p.getCurrentLocation().getPointer();
280 StringRef(curPtr, fullString.size() - (curPtr - fullString.data()));
282 if (typeString.starts_with(
"array<") || typeString.starts_with(
"inout<") ||
283 typeString.starts_with(
"uarray<") || typeString.starts_with(
"struct<") ||
284 typeString.starts_with(
"typealias<") || typeString.starts_with(
"int<") ||
285 typeString.starts_with(
"enum<") || typeString.starts_with(
"union<")) {
286 llvm::StringRef mnemonic;
287 if (
auto parseResult = generatedTypeParser(p, &mnemonic, result);
288 parseResult.has_value())
290 return p.emitError(p.getNameLoc(),
"invalid type `") << typeString <<
"`";
293 return p.parseType(result);
297 if (succeeded(generatedTypePrinter(element, p)))
299 p.printType(element);
306Type IntType::get(mlir::TypedAttr width) {
308 auto widthWidth = llvm::dyn_cast<IntegerType>(width.getType());
309 assert(widthWidth && widthWidth.getWidth() == 32 &&
310 "!hw.int width must be 32-bits");
313 if (
auto cstWidth = llvm::dyn_cast<IntegerAttr>(width))
314 return IntegerType::get(width.getContext(),
315 cstWidth.getValue().getZExtValue());
317 return Base::get(width.getContext(), width);
320Type IntType::parse(AsmParser &p) {
322 auto int32Type = p.getBuilder().getIntegerType(32);
324 mlir::TypedAttr width;
325 if (p.parseLess() || p.parseAttribute(width, int32Type) || p.parseGreater())
330void IntType::print(AsmPrinter &p)
const {
332 p.printAttributeWithoutType(
getWidth());
340Type StructType::parse(AsmParser &p) {
341 llvm::SmallVector<FieldInfo, 4> parameters;
342 SmallVector<std::pair<llvm::SMLoc, StringAttr>> duplicates;
344 for (
auto [loc, name] : duplicates)
345 p.emitError(loc) <<
"duplicate field name '" << name.getValue() <<
"'";
346 if (failed(parseResult) || !duplicates.empty())
348 return get(p.getContext(), parameters);
351LogicalResult StructType::verify(function_ref<InFlightDiagnostic()> emitError,
352 ArrayRef<StructType::FieldInfo> elements) {
353 llvm::SmallDenseSet<StringAttr> fieldNameSet;
354 LogicalResult result =
success();
355 fieldNameSet.reserve(elements.size());
356 for (
const auto &elt : elements)
357 if (!fieldNameSet.insert(elt.name).second) {
359 emitError() <<
"duplicate field name '" << elt.name.getValue()
360 <<
"' in hw.struct type";
365void StructType::print(AsmPrinter &p)
const {
369Type StructType::getFieldType(mlir::StringRef fieldName) {
370 for (
const auto &field : getElements())
371 if (field.name == fieldName)
376std::optional<uint32_t> StructType::getFieldIndex(mlir::StringRef fieldName) {
377 ArrayRef<hw::StructType::FieldInfo> elems = getElements();
378 for (
size_t idx = 0, numElems = elems.size(); idx < numElems; ++idx)
379 if (elems[idx].name == fieldName)
384std::optional<uint32_t> StructType::getFieldIndex(mlir::StringAttr fieldName) {
385 ArrayRef<hw::StructType::FieldInfo> elems = getElements();
386 for (
size_t idx = 0, numElems = elems.size(); idx < numElems; ++idx)
387 if (elems[idx].name == fieldName)
392static std::pair<uint64_t, SmallVector<uint64_t>>
394 uint64_t fieldID = 0;
395 auto elements = st.getElements();
396 SmallVector<uint64_t> fieldIDs;
397 fieldIDs.reserve(elements.size());
398 for (
auto &element : elements) {
399 auto type = element.type;
401 fieldIDs.push_back(fieldID);
405 return {fieldID, fieldIDs};
408void StructType::getInnerTypes(SmallVectorImpl<Type> &types) {
409 for (
const auto &field : getElements())
410 types.push_back(field.type);
413uint64_t StructType::getMaxFieldID()
const {
414 uint64_t fieldID = 0;
415 for (
const auto &field : getElements())
420std::pair<Type, uint64_t>
421StructType::getSubTypeByFieldID(uint64_t fieldID)
const {
425 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
426 auto subfieldIndex = std::distance(fieldIDs.begin(), it);
427 auto subfieldType = getElements()[subfieldIndex].type;
428 auto subfieldID = fieldID - fieldIDs[subfieldIndex];
429 return {subfieldType, subfieldID};
432std::pair<uint64_t, bool>
433StructType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
435 auto childRoot = fieldIDs[index];
437 index + 1 >= getElements().size() ? maxId : (fieldIDs[index + 1] - 1);
438 return std::make_pair(fieldID - childRoot,
439 fieldID >= childRoot && fieldID <= rangeEnd);
442uint64_t StructType::getFieldID(uint64_t index)
const {
444 return fieldIDs[index];
447uint64_t StructType::getIndexForFieldID(uint64_t fieldID)
const {
448 assert(!getElements().
empty() &&
"Bundle must have >0 fields");
450 auto *it = std::prev(llvm::upper_bound(fieldIDs, fieldID));
451 return std::distance(fieldIDs.begin(), it);
454std::pair<uint64_t, uint64_t>
455StructType::getIndexAndSubfieldID(uint64_t fieldID)
const {
458 return {index, fieldID - elementFieldID};
461std::optional<DenseMap<Attribute, Type>>
462hw::StructType::getSubelementIndexMap()
const {
463 DenseMap<Attribute, Type> destructured;
464 for (
auto [i, field] : llvm::enumerate(getElements()))
466 {IntegerAttr::get(IndexType::get(getContext()), i), field.type});
470Type hw::StructType::getTypeAtIndex(Attribute index)
const {
471 auto indexAttr = llvm::dyn_cast<IntegerAttr>(index);
478std::optional<int64_t> StructType::getBitWidth()
const {
480 for (
auto field : getElements()) {
507Type UnionType::parse(AsmParser &p) {
508 llvm::SmallVector<FieldInfo, 4> parameters;
509 llvm::StringSet<> nameSet;
510 bool hasDuplicateName =
false;
511 if (p.parseCommaSeparatedList(
512 mlir::AsmParser::Delimiter::LessGreater, [&]() -> ParseResult {
516 auto fieldLoc = p.getCurrentLocation();
517 if (p.parseKeyword(&name) || p.parseColon() || p.parseType(type))
520 if (!nameSet.insert(name).second) {
521 p.emitError(fieldLoc,
"duplicate field name \'" + name +
522 "\' in hw.union type");
525 hasDuplicateName = true;
529 if (succeeded(p.parseOptionalKeyword(
"offset")))
530 if (p.parseInteger(offset))
532 parameters.push_back(UnionType::FieldInfo{
533 StringAttr::get(p.getContext(), name), type, offset});
538 if (hasDuplicateName)
541 return get(p.getContext(), parameters);
544void UnionType::print(AsmPrinter &odsPrinter)
const {
546 llvm::interleaveComma(
547 getElements(), odsPrinter, [&](
const UnionType::FieldInfo &field) {
548 odsPrinter << field.name.getValue() <<
": " << field.type;
550 odsPrinter <<
" offset " << field.offset;
555LogicalResult UnionType::verify(function_ref<InFlightDiagnostic()> emitError,
556 ArrayRef<UnionType::FieldInfo> elements) {
557 llvm::SmallDenseSet<StringAttr> fieldNameSet;
558 LogicalResult result =
success();
559 fieldNameSet.reserve(elements.size());
560 for (
const auto &elt : elements)
561 if (!fieldNameSet.insert(elt.name).second) {
563 emitError() <<
"duplicate field name '" << elt.name.getValue()
564 <<
"' in hw.union type";
569std::optional<uint32_t> UnionType::getFieldIndex(mlir::StringAttr fieldName) {
570 ArrayRef<hw::UnionType::FieldInfo> elems = getElements();
571 for (
size_t idx = 0, numElems = elems.size(); idx < numElems; ++idx)
572 if (elems[idx].name == fieldName)
577std::optional<uint32_t> UnionType::getFieldIndex(mlir::StringRef fieldName) {
578 return getFieldIndex(StringAttr::get(getContext(), fieldName));
581UnionType::FieldInfo UnionType::getFieldInfo(::mlir::StringRef fieldName) {
582 if (
auto fieldIndex = getFieldIndex(fieldName))
583 return getElements()[*fieldIndex];
587Type UnionType::getFieldType(mlir::StringRef fieldName) {
588 return getFieldInfo(fieldName).type;
591std::optional<int64_t> UnionType::getBitWidth()
const {
593 for (
auto field : getElements()) {
597 fieldSize += field.offset;
598 if (fieldSize > maxSize)
608Type EnumType::parse(AsmParser &p) {
609 llvm::SmallVector<Attribute> fields;
611 if (p.parseCommaSeparatedList(AsmParser::Delimiter::LessGreater, [&]() {
613 if (p.parseKeyword(&name))
615 fields.push_back(StringAttr::get(p.getContext(), name));
620 return get(p.getContext(), ArrayAttr::get(p.getContext(), fields));
623void EnumType::print(AsmPrinter &p)
const {
625 llvm::interleaveComma(getFields(), p, [&](Attribute enumerator) {
626 p << llvm::cast<StringAttr>(enumerator).getValue();
631bool EnumType::contains(mlir::StringRef field) {
632 return indexOf(field).has_value();
635std::optional<size_t> EnumType::indexOf(mlir::StringRef field) {
636 for (
auto it : llvm::enumerate(getFields()))
637 if (llvm::cast<StringAttr>(it.value()).getValue() == field)
642std::optional<int64_t> EnumType::getBitWidth()
const {
643 auto w = getFields().size();
645 return llvm::Log2_64_Ceil(w);
653static ParseResult
parseHWArray(AsmParser &p, Attribute &dim, Type &inner) {
655 auto int64Type = p.getBuilder().getIntegerType(64);
657 if (
auto res = p.parseOptionalInteger(dimLiteral); res.has_value()) {
660 dim = p.getBuilder().getI64IntegerAttr(dimLiteral);
661 }
else if (
auto res64 = p.parseOptionalAttribute(dim, int64Type);
666 return p.emitError(p.getNameLoc(),
"expected integer");
668 if (!isa<IntegerAttr, ParamExprAttr, ParamDeclRefAttr>(dim)) {
669 p.emitError(p.getNameLoc(),
"unsupported dimension kind in hw.array");
680 p.printAttributeWithoutType(dim);
685size_t ArrayType::getNumElements()
const {
686 if (
auto intAttr = llvm::dyn_cast<IntegerAttr>(getSizeAttr()))
687 return intAttr.getInt();
691LogicalResult ArrayType::verify(function_ref<InFlightDiagnostic()> emitError,
692 Type innerType, Attribute size) {
694 return emitError() <<
"hw.array cannot contain InOut types";
698uint64_t ArrayType::getMaxFieldID()
const {
699 return getNumElements() *
703std::pair<Type, uint64_t>
704ArrayType::getSubTypeByFieldID(uint64_t fieldID)
const {
710std::pair<uint64_t, bool>
711ArrayType::projectToChildFieldID(uint64_t fieldID, uint64_t index)
const {
715 return std::make_pair(fieldID - childRoot,
716 fieldID >= childRoot && fieldID <= rangeEnd);
719uint64_t ArrayType::getIndexForFieldID(uint64_t fieldID)
const {
720 assert(fieldID &&
"fieldID must be at least 1");
725std::pair<uint64_t, uint64_t>
726ArrayType::getIndexAndSubfieldID(uint64_t fieldID)
const {
729 return {index, fieldID - elementFieldID};
732uint64_t ArrayType::getFieldID(uint64_t index)
const {
736std::optional<DenseMap<Attribute, Type>>
737hw::ArrayType::getSubelementIndexMap()
const {
738 DenseMap<Attribute, Type> destructured;
739 for (
unsigned i = 0; i < getNumElements(); ++i)
741 {IntegerAttr::get(IndexType::get(getContext()), i), getElementType()});
745Type hw::ArrayType::getTypeAtIndex(Attribute index)
const {
746 return getElementType();
749std::optional<int64_t> hw::ArrayType::getBitWidth()
const {
751 if (elementBitWidth < 0)
764UnpackedArrayType::verify(function_ref<InFlightDiagnostic()> emitError,
765 Type innerType, Attribute size) {
767 return emitError() <<
"invalid element for uarray type";
771size_t UnpackedArrayType::getNumElements()
const {
772 if (
auto intAttr = llvm::dyn_cast<IntegerAttr>(getSizeAttr()))
773 return intAttr.getInt();
777uint64_t UnpackedArrayType::getMaxFieldID()
const {
778 return getNumElements() *
782std::pair<Type, uint64_t>
783UnpackedArrayType::getSubTypeByFieldID(uint64_t fieldID)
const {
789std::pair<uint64_t, bool>
790UnpackedArrayType::projectToChildFieldID(uint64_t fieldID,
791 uint64_t index)
const {
795 return std::make_pair(fieldID - childRoot,
796 fieldID >= childRoot && fieldID <= rangeEnd);
799uint64_t UnpackedArrayType::getIndexForFieldID(uint64_t fieldID)
const {
800 assert(fieldID &&
"fieldID must be at least 1");
805std::pair<uint64_t, uint64_t>
806UnpackedArrayType::getIndexAndSubfieldID(uint64_t fieldID)
const {
809 return {index, fieldID - elementFieldID};
812uint64_t UnpackedArrayType::getFieldID(uint64_t index)
const {
816std::optional<int64_t> UnpackedArrayType::getBitWidth()
const {
818 if (elementBitWidth < 0)
820 int64_t dimBitWidth = getNumElements();
823 return (int64_t)getNumElements() * elementBitWidth;
830LogicalResult InOutType::verify(function_ref<InFlightDiagnostic()> emitError,
833 return emitError() <<
"invalid element for hw.inout type " <<
innerType;
841TypeAliasType TypeAliasType::get(SymbolRefAttr ref, Type innerType) {
846TypeAliasType::getChecked(function_ref<InFlightDiagnostic()> emitError,
847 SymbolRefAttr ref, Type innerType) {
848 return getChecked(emitError, ref.getContext(), ref, innerType,
853TypeAliasType::verify(function_ref<InFlightDiagnostic()> emitError,
854 SymbolRefAttr ref, Type innerType, Type canonicalType) {
855 if (ref.getNestedReferences().size() != 1)
857 <<
"expected exactly one nested reference in hw.typealias";
861Type TypeAliasType::parse(AsmParser &p) {
864 if (p.parseLess() || p.parseAttribute(ref) || p.parseComma() ||
865 p.parseType(type) || p.parseGreater())
868 return p.getChecked<TypeAliasType>(ref, type);
871void TypeAliasType::print(AsmPrinter &p)
const {
872 p <<
"<" << getRef() <<
", " << getInnerType() <<
">";
877TypedeclOp TypeAliasType::getTypeDecl(
const HWSymbolCache &cache) {
878 SymbolRefAttr ref = getRef();
879 auto typeScope = ::dyn_cast_or_null<TypeScopeLike>(
884 return dyn_cast_or_null<TypedeclOp>(
885 SymbolTable::lookupSymbolIn(typeScope, ref.getLeafReference()));
888std::optional<int64_t> TypeAliasType::getBitWidth()
const {
899size_t ModuleType::getPortIdForInputId(
size_t idx) {
900 assert(idx < getImpl()->inputToAbs.size() &&
"input port out of range");
901 return getImpl()->inputToAbs[idx];
904size_t ModuleType::getPortIdForOutputId(
size_t idx) {
905 assert(idx < getImpl()->outputToAbs.size() &&
" output port out of range");
906 return getImpl()->outputToAbs[idx];
909size_t ModuleType::getInputIdForPortId(
size_t idx) {
910 auto nIdx = getImpl()->absToInput[idx];
915size_t ModuleType::getOutputIdForPortId(
size_t idx) {
916 auto nIdx = getImpl()->absToOutput[idx];
921size_t ModuleType::getNumInputs() {
return getImpl()->inputToAbs.size(); }
923size_t ModuleType::getNumOutputs() {
return getImpl()->outputToAbs.size(); }
925size_t ModuleType::getNumPorts() {
return getPorts().size(); }
927SmallVector<Type> ModuleType::getInputTypes() {
928 SmallVector<Type> retval;
929 for (
auto &p : getPorts()) {
931 retval.push_back(p.type);
936SmallVector<Type> ModuleType::getOutputTypes() {
937 SmallVector<Type> retval;
938 for (
auto &p : getPorts())
940 retval.push_back(p.type);
944SmallVector<Type> ModuleType::getPortTypes() {
945 SmallVector<Type> retval;
946 for (
auto &p : getPorts())
947 retval.push_back(p.type);
951Type ModuleType::getInputType(
size_t idx) {
952 return getPorts()[getPortIdForInputId(idx)].type;
955Type ModuleType::getOutputType(
size_t idx) {
956 return getPorts()[getPortIdForOutputId(idx)].type;
959SmallVector<Attribute> ModuleType::getInputNames() {
960 SmallVector<Attribute> retval;
961 for (
auto &p : getPorts())
963 retval.push_back(p.name);
967SmallVector<Attribute> ModuleType::getOutputNames() {
968 SmallVector<Attribute> retval;
969 for (
auto &p : getPorts())
971 retval.push_back(p.name);
975StringAttr ModuleType::getPortNameAttr(
size_t idx) {
976 return getPorts()[idx].name;
979StringRef ModuleType::getPortName(
size_t idx) {
980 auto sa = getPortNameAttr(idx);
982 return sa.getValue();
986StringAttr ModuleType::getInputNameAttr(
size_t idx) {
987 return getPorts()[getPortIdForInputId(idx)].name;
990StringRef ModuleType::getInputName(
size_t idx) {
991 auto sa = getInputNameAttr(idx);
993 return sa.getValue();
997StringAttr ModuleType::getOutputNameAttr(
size_t idx) {
998 return getPorts()[getPortIdForOutputId(idx)].name;
1001StringRef ModuleType::getOutputName(
size_t idx) {
1002 auto sa = getOutputNameAttr(idx);
1004 return sa.getValue();
1008bool ModuleType::isOutput(
size_t idx) {
1009 auto &p = getPorts()[idx];
1013FunctionType ModuleType::getFuncType() {
1014 SmallVector<Type> inputs, outputs;
1015 for (
auto p : getPorts())
1017 inputs.push_back(p.type);
1019 outputs.push_back(p.type);
1020 return FunctionType::get(getContext(), inputs, outputs);
1023ArrayRef<ModulePort> ModuleType::getPorts()
const {
1024 return getImpl()->getPorts();
1027FailureOr<ModuleType> ModuleType::resolveParametricTypes(ArrayAttr parameters,
1030 SmallVector<ModulePort, 8> resolvedPorts;
1032 FailureOr<Type> resolvedType =
1034 if (failed(resolvedType))
1036 port.type = *resolvedType;
1037 resolvedPorts.push_back(port);
1039 return ModuleType::get(getContext(), resolvedPorts);
1049 llvm_unreachable(
"invalid direction");
1055 if (str ==
"output")
1057 llvm::report_fatal_error(
"invalid direction");
1063 SmallVectorImpl<ModulePort> &ports) {
1064 return p.parseCommaSeparatedList(
1065 mlir::AsmParser::Delimiter::LessGreater, [&]() -> ParseResult {
1069 if (p.parseKeyword(&dir) || p.parseKeywordOrString(&name) ||
1070 p.parseColon() || p.parseType(type))
1073 {StringAttr::get(p.getContext(), name), type,
strToDir(dir)});
1079static void printPorts(AsmPrinter &p, ArrayRef<ModulePort> ports) {
1081 llvm::interleaveComma(ports, p, [&](
const ModulePort &port) {
1083 p.printKeywordOrString(port.
name.getValue());
1084 p <<
" : " << port.
type;
1089Type ModuleType::parse(AsmParser &odsParser) {
1090 llvm::SmallVector<ModulePort, 4> ports;
1093 return get(odsParser.getContext(), ports);
1096void ModuleType::print(AsmPrinter &odsPrinter)
const {
1101 ArrayRef<Attribute> inputNames,
1102 ArrayRef<Attribute> outputNames) {
1104 cast<FunctionType>(cast<mlir::FunctionOpInterface>(op).getFunctionType()),
1105 inputNames, outputNames);
1109 ArrayRef<Attribute> inputNames,
1110 ArrayRef<Attribute> outputNames) {
1111 SmallVector<ModulePort> ports;
1112 if (!inputNames.empty()) {
1113 for (
auto [t, n] : llvm::zip_equal(fnty.getInputs(), inputNames))
1116 for (
auto t : fnty.getInputs())
1119 if (!outputNames.empty()) {
1120 for (
auto [t, n] : llvm::zip_equal(fnty.getResults(), outputNames))
1123 for (
auto t : fnty.getResults())
1126 return ModuleType::get(fnty.getContext(), ports);
1131 size_t nextInput = 0;
1132 size_t nextOutput = 0;
1133 for (
auto [idx, p] : llvm::enumerate(
ports)) {
1152void HWDialect::registerTypes() {
1154#define GET_TYPEDEF_LIST
1155#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 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 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)
false return failure()
Parse an optional keyword or string and set instance into 'result'.
if(parseOptionalKeywordOrOptionalString(parser, result.rawName, found)) return failure()
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.
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)
::circt::FieldInfo FieldInfo
Struct defining a field. Used in structs.
llvm::hash_code hash_value(const OffsetFieldInfo &fi)
bool operator==(const OffsetFieldInfo &a, const OffsetFieldInfo &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 ...
bool isValidProbeElementType(mlir::Type type)
Return true if type is a valid probe payload.
LogicalResult aggregateAttrToAPInt(mlir::Type type, ArrayAttr attr, APInt &result)
Convert an ArrayAttr into an APInt value matching the given type.
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.
LogicalResult apIntToAggregateAttr(mlir::Type aggregateType, const APInt &intVal, ArrayAttr &result)
Convert an APInt value into a nested aggregate attribute matching the given HWAggregateType.
bool isHWEnumType(mlir::Type type)
Return true if the specified type is a HW Enum type.
mlir::Type getCanonicalType(mlir::Type type)
Recursively remove HW type aliases from a type and its subelements.
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.
ParseResult parseFieldList(AsmParser &p, SmallVectorImpl< FieldInfo > &fields, SmallVectorImpl< std::pair< llvm::SMLoc, StringAttr > > &duplicates)
Parse a list of named fields within <>, e.g.
void printFieldList(AsmPrinter &p, ArrayRef< FieldInfo > fields)
Print a list of fields within <>, e.g. <foo: i7, bar: i8>.
Interface for dialects to classify their types as valid probe payloads.
virtual bool isValidProbeElementType(mlir::Type type) const =0
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.