18#include "mlir/IR/ImplicitLocOpBuilder.h"
19#include "llvm/ADT/TypeSwitch.h"
20#include "llvm/Support/Path.h"
23using namespace firrtl;
27 ImplicitLocOpBuilder locBuilder(loc, builder.getInsertionBlock(),
28 builder.getInsertionPoint());
30 builder.restoreInsertionPoint(locBuilder.saveInsertionPoint());
36 auto dstFType = type_cast<FIRRTLType>(dst.getType());
37 auto srcFType = type_cast<FIRRTLType>(src.getType());
38 auto dstType = type_dyn_cast<FIRRTLBaseType>(dstFType);
39 auto srcType = type_dyn_cast<FIRRTLBaseType>(srcFType);
43 if (type_isa<RefType>(dstFType)) {
44 if (dstFType != srcFType)
45 src = builder.create<RefCastOp>(dstFType, src);
46 builder.create<RefDefineOp>(dst, src);
47 }
else if (type_isa<PropertyType>(dstFType) &&
48 type_isa<PropertyType>(srcFType)) {
50 builder.create<PropAssignOp>(dst, src);
53 builder.create<ConnectOp>(dst, src);
59 if (isa<AnalogType>(dstType)) {
60 builder.create<AttachOp>(ArrayRef{dst, src});
65 if (dstType == srcType && dstType.isPassive() &&
66 !dstType.hasUninferredWidth()) {
67 builder.create<MatchingConnectOp>(dst, src);
71 if (
auto dstBundle = type_dyn_cast<BundleType>(dstType)) {
76 auto srcBundle = type_dyn_cast<BundleType>(srcType);
77 if (!srcBundle ||
numElements != srcBundle.getNumElements()) {
78 builder.create<ConnectOp>(dst, src);
82 auto dstField = builder.create<SubfieldOp>(dst, i);
83 auto srcField = builder.create<SubfieldOp>(src, i);
84 if (dstBundle.getElement(i).isFlip)
85 std::swap(dstField, srcField);
91 if (
auto dstVector = type_dyn_cast<FVectorType>(dstType)) {
96 auto srcVector = type_dyn_cast<FVectorType>(srcType);
97 if (!srcVector ||
numElements != srcVector.getNumElements()) {
98 builder.create<ConnectOp>(dst, src);
102 auto dstField = builder.create<SubindexOp>(dst, i);
103 auto srcField = builder.create<SubindexOp>(src, i);
109 if ((dstType.hasUninferredReset() || srcType.hasUninferredReset()) &&
110 dstType != srcType) {
111 srcType = dstType.getConstType(srcType.isConst());
112 src = builder.create<UninferredResetCastOp>(srcType, src);
116 auto dstWidth = dstType.getBitWidthOrSentinel();
117 auto srcWidth = srcType.getBitWidthOrSentinel();
118 if (dstWidth < 0 || srcWidth < 0) {
125 if (dstType != srcType && dstType.getWidthlessType() != srcType &&
127 src = builder.create<ConstCastOp>(dstType.getWidthlessType(), src);
130 builder.create<ConnectOp>(dst, src);
135 if (dstWidth < srcWidth) {
138 type_cast<IntType>(dstType).
getConstType(srcType.isConst());
139 bool isSignedDest = tmpType.
isSigned();
142 UIntType::get(dstType.getContext(), dstWidth, srcType.isConst());
143 src = builder.create<TailPrimOp>(tmpType, src, srcWidth - dstWidth);
146 src = builder.create<AsSIntPrimOp>(
147 dstType.getConstType(tmpType.
isConst()), src);
148 }
else if (srcWidth < dstWidth) {
150 src = builder.create<PadPrimOp>(src, dstWidth);
153 if (
auto srcType = type_cast<FIRRTLBaseType>(src.getType());
154 srcType && dstType != srcType &&
156 src = builder.create<ConstCastOp>(dstType, src);
161 if (dstType == src.getType() && dstType.isPassive() &&
162 !dstType.hasUninferredWidth()) {
163 builder.create<MatchingConnectOp>(dst, src);
165 builder.create<ConnectOp>(dst, src);
169 auto intType = type_cast<IntType>(type);
170 assert((!intType.hasWidth() ||
171 (
unsigned)intType.getWidthOrSentinel() == value.getBitWidth()) &&
172 "value / type width mismatch");
174 intType.isSigned() ? IntegerType::Signed : IntegerType::Unsigned;
176 IntegerType::get(type.getContext(), value.getBitWidth(), intSign);
177 return IntegerAttr::get(attrType, value);
183 int32_t width = abs(type_cast<IntType>(type).getWidthOrSentinel());
190 int32_t width = abs(type_cast<IntType>(type).getWidthOrSentinel());
192 type, APInt(width, -1,
false,
true));
198 for (
auto *user : value.getUsers())
199 if (
auto propassign = dyn_cast<PropAssignOp>(user))
200 if (propassign.getDest() == value)
215 for (
auto *user : val.getUsers()) {
216 if (
auto connect = dyn_cast<FConnectLike>(user)) {
217 if (connect.getDest() != val)
219 return connect.getSrc();
226 bool lookThroughNodes,
227 bool lookThroughCasts) {
232 auto updateVal = [&](Value thisVal) {
233 for (
auto *user : thisVal.getUsers()) {
234 if (
auto connect = dyn_cast<FConnectLike>(user)) {
235 if (connect.getDest() != val)
237 val = connect.getSrc();
247 if (
auto blockArg = dyn_cast<BlockArgument>(val)) {
248 FModuleOp op = cast<FModuleOp>(val.getParentBlock()->getParentOp());
249 auto direction = op.getPortDirection(blockArg.getArgNumber());
251 if (direction == Direction::In)
257 auto *op = val.getDefiningOp();
260 if (
auto inst = dyn_cast<InstanceOp>(op)) {
261 auto resultNo = cast<OpResult>(val).getResultNumber();
263 if (inst.getPortDirection(resultNo) == Direction::Out)
264 return inst.getResult(resultNo);
271 updateVal(op->getResult(0));
276 if (lookThroughNodes && isa<NodeOp>(op)) {
277 val = cast<NodeOp>(op).getInput();
281 if (lookThroughCasts &&
282 isa<AsUIntPrimOp, AsSIntPrimOp, AsClockPrimOp, AsAsyncResetPrimOp>(
284 val = op->getOperand(0);
289 if (isa<PadPrimOp, TailPrimOp>(op)) {
290 val = op->getOperand(0);
305 bool lookThroughNodes,
bool lookThroughCasts,
309 assert(value.getType().isPassive() &&
"this code was not tested with flips");
320 struct StackElement {
322 : dst(dst), src(src), current(current), it(current.user_begin()),
335 Value::user_iterator it;
339 SmallVector<StackElement> workStack;
346 workStack.emplace_back(dst, src, value, src.
getFieldID());
352 auto fieldRef = original;
360 auto val = fieldRef.getValue();
363 if (
auto blockArg = dyn_cast<BlockArgument>(val)) {
364 auto *parent = val.getParentBlock()->getParentOp();
365 auto module = cast<FModuleLike>(parent);
366 auto direction =
module.getPortDirection(blockArg.getArgNumber());
368 if (direction == Direction::In) {
369 if (!callback(original, fieldRef))
373 addToWorklist(original, fieldRef);
377 auto *op = val.getDefiningOp();
380 if (
auto inst = dyn_cast<InstanceOp>(op)) {
381 auto resultNo = cast<OpResult>(val).getResultNumber();
383 if (inst.getPortDirection(resultNo) == Direction::Out) {
384 if (!callback(original, fieldRef))
388 addToWorklist(original, fieldRef);
394 addToWorklist(original, fieldRef);
399 if (lookThroughNodes && isa<NodeOp>(op)) {
400 auto input = cast<NodeOp>(op).getInput();
402 fieldRef = next.getSubField(fieldRef.getFieldID());
407 if (lookThroughCasts &&
408 isa<AsUIntPrimOp, AsSIntPrimOp, AsClockPrimOp, AsAsyncResetPrimOp>(
410 auto input = op->getOperand(0);
412 fieldRef = next.getSubField(fieldRef.getFieldID());
417 if (isa<PadPrimOp, TailPrimOp>(op)) {
418 auto input = op->getOperand(0);
420 fieldRef = next.getSubField(fieldRef.getFieldID());
429 if (!callback(original, fieldRef))
437 if (workStack.empty())
439 auto &back = workStack.back();
440 auto current = back.current;
442 if (back.it == current.user_end()) {
443 workStack.pop_back();
449 auto *user = *back.it++;
450 auto fieldID = back.fieldID;
452 if (
auto subfield = dyn_cast<SubfieldOp>(user)) {
453 BundleType bundleType = subfield.getInput().getType();
454 auto index = subfield.getFieldIndex();
455 auto subID = bundleType.getFieldID(index);
457 if (fieldID && index != bundleType.getIndexForFieldID(fieldID))
459 auto subRef = fieldRef.getSubField(subID);
460 auto subOriginal = original.getSubField(subID);
461 auto value = subfield.getResult();
464 workStack.emplace_back(subOriginal, subRef, value, 0);
467 workStack.emplace_back(subOriginal, subRef, value, fieldID - subID);
469 }
else if (
auto subindex = dyn_cast<SubindexOp>(user)) {
470 FVectorType vectorType = subindex.getInput().getType();
471 auto index = subindex.getIndex();
472 auto subID = vectorType.getFieldID(index);
474 if (fieldID && index != vectorType.getIndexForFieldID(fieldID))
476 auto subRef = fieldRef.getSubField(subID);
477 auto subOriginal = original.getSubField(subID);
478 auto value = subindex.getResult();
481 workStack.emplace_back(subOriginal, subRef, value, 0);
484 workStack.emplace_back(subOriginal, subRef, value, fieldID - subID);
486 }
else if (
auto connect = dyn_cast<FConnectLike>(user)) {
488 if (connect.getDest() != current)
506 if (LLVM_UNLIKELY(!value))
510 auto *op = value.getDefiningOp();
517 return TypeSwitch<Operation *, FieldRef>(op)
518 .Case<RefCastOp, ConstCastOp, UninferredResetCastOp>(
519 [lookThroughCasts](
auto op) {
520 if (!lookThroughCasts)
524 .Case<SubfieldOp, OpenSubfieldOp, SubindexOp, OpenSubindexOp, RefSubOp,
526 [](
auto subOp) {
return subOp.getAccessedField(); })
531 bool lookThroughCasts) {
532 if (LLVM_UNLIKELY(!value))
538 auto deltaRef =
getDeltaRef(value, lookThroughCasts);
542 id = deltaRef.getSubField(
id).getFieldID();
544 value = deltaRef.getValue();
549static void getDeclName(Value value, SmallString<64> &
string,
bool nameSafe) {
552 if (
auto arg = dyn_cast<BlockArgument>(value)) {
554 auto *op = arg.getOwner()->getParentOp();
555 TypeSwitch<Operation *>(op).Case<FModuleOp, ClassOp>([&](
auto op) {
556 auto name = cast<StringAttr>(op.getPortNames()[arg.getArgNumber()]);
557 string += name.getValue();
562 auto *op = value.getDefiningOp();
563 TypeSwitch<Operation *>(op)
564 .Case<ObjectOp>([&](ObjectOp op) {
565 string += op.getInstanceName();
568 .Case<InstanceOp, MemOp>([&](
auto op) {
569 string += op.getName();
570 string += nameSafe ?
"_" :
".";
571 string += op.getPortName(cast<OpResult>(value).getResultNumber())
575 .Case<FNamableOp>([&](
auto op) {
576 string += op.getName();
579 .Case<mlir::UnrealizedConversionCastOp>(
580 [&](mlir::UnrealizedConversionCastOp cast) {
582 if (cast.getNumResults() == 1 && cast.getNumOperands() == 1 &&
583 cast.getResult(0).getType() == cast.getOperand(0).getType()) {
584 value = cast.getInputs()[0];
599std::pair<std::string, bool>
601 SmallString<64> name;
604 bool rootKnown = !name.empty();
606 auto type = value.getType();
610 if (
auto refTy = type_dyn_cast<RefType>(type))
611 type = refTy.getType();
613 if (
auto bundleType = type_dyn_cast<BundleType>(type)) {
614 auto index = bundleType.getIndexForFieldID(localID);
616 auto &element = bundleType.getElements()[index];
618 name += nameSafe ?
"_" :
".";
619 name += element.name.getValue();
622 localID = localID - bundleType.getFieldID(index);
623 }
else if (
auto bundleType = type_dyn_cast<OpenBundleType>(type)) {
624 auto index = bundleType.getIndexForFieldID(localID);
626 auto &element = bundleType.getElements()[index];
628 name += nameSafe ?
"_" :
".";
629 name += element.name.getValue();
632 localID = localID - bundleType.getFieldID(index);
633 }
else if (
auto vecType = type_dyn_cast<FVectorType>(type)) {
634 auto index = vecType.getIndexForFieldID(localID);
635 name += nameSafe ?
"_" :
"[";
636 name += std::to_string(index);
640 type = vecType.getElementType();
641 localID = localID - vecType.getFieldID(index);
642 }
else if (
auto vecType = type_dyn_cast<OpenVectorType>(type)) {
643 auto index = vecType.getIndexForFieldID(localID);
644 name += nameSafe ?
"_" :
"[";
645 name += std::to_string(index);
649 type = vecType.getElementType();
650 localID = localID - vecType.getFieldID(index);
651 }
else if (
auto enumType = type_dyn_cast<FEnumType>(type)) {
652 auto index = enumType.getIndexForFieldID(localID);
653 auto &element = enumType.getElements()[index];
654 name += nameSafe ?
"_" :
".";
655 name += element.name.getValue();
657 localID = localID - enumType.getFieldID(index);
658 }
else if (
auto classType = type_dyn_cast<ClassType>(type)) {
659 auto index = classType.getIndexForFieldID(localID);
660 auto &element = classType.getElement(index);
661 name += nameSafe ?
"_" :
".";
662 name += element.name.getValue();
664 localID = localID - classType.getFieldID(index);
670 llvm_unreachable(
"unsupported type");
674 return {name.str().str(), rootKnown};
682 Value value,
unsigned fieldID) {
684 while (fieldID != 0) {
686 .
Case<BundleType, OpenBundleType>([&](
auto bundle) {
687 auto index = bundle.getIndexForFieldID(fieldID);
688 value = builder.create<SubfieldOp>(value, index);
689 fieldID -= bundle.getFieldID(index);
691 .Case<FVectorType, OpenVectorType>([&](
auto vector) {
692 auto index = vector.getIndexForFieldID(fieldID);
693 value = builder.create<SubindexOp>(value, index);
694 fieldID -= vector.getFieldID(index);
696 .Case<RefType>([&](
auto reftype) {
698 .template Case<BundleType, FVectorType>([&](
auto type) {
699 auto index = type.getIndexForFieldID(fieldID);
700 value = builder.create<RefSubOp>(value, index);
701 fieldID -= type.getFieldID(index);
703 .Default([&](
auto _) {
704 llvm::report_fatal_error(
705 "unrecognized type for indexing through with fieldID");
709 .Default([&](
auto _) {
710 llvm::report_fatal_error(
711 "unrecognized type for indexing through with fieldID");
731 return fn(0, type,
false);
733 uint64_t fieldID = 0;
734 auto recurse = [&](
auto &&f,
FIRRTLBaseType type,
bool isFlip) ->
void {
736 .
Case<BundleType>([&](BundleType bundle) {
737 for (
size_t i = 0, e = bundle.getNumElements(); i < e; ++i) {
739 f(f, bundle.getElementType(i),
740 isFlip ^ bundle.getElement(i).isFlip);
743 .
template Case<FVectorType>([&](FVectorType vector) {
744 for (
size_t i = 0, e = vector.getNumElements(); i < e; ++i) {
746 f(f, vector.getElementType(), isFlip);
749 .
template Case<FEnumType>([&](FEnumType fenum) {
750 for (
size_t i = 0, e = fenum.getNumElements(); i < e; ++i) {
752 f(f, fenum.getElementType(i), isFlip);
756 assert(groundType.isGround() &&
757 "only ground types are expected here");
758 fn(fieldID, groundType, isFlip);
761 recurse(recurse, type,
false);
768 if (
auto arg = dyn_cast<BlockArgument>(root)) {
769 auto mod = cast<FModuleLike>(arg.getOwner()->getParentOp());
780 return TypeSwitch<Operation *, FieldRef>(ist.
getOp())
781 .Case<FModuleOp>([&](
auto fmod) {
787 auto symOp = dyn_cast<hw::InnerSymbolOpInterface>(ist.
getOp());
788 assert(symOp && symOp.getTargetResultIndex() &&
789 (symOp.supportsPerFieldSymbols() || ist.
getField() == 0));
795 MLIRContext *context, hw::InnerSymAttr attr, uint64_t fieldID,
797 SmallVector<hw::InnerSymPropertiesAttr> props;
800 if (
auto sym = attr.getSymIfExists(fieldID))
802 llvm::append_range(props, attr.getProps());
806 auto sym = StringAttr::get(context, getNamespace().newName(
"sym"));
807 props.push_back(hw::InnerSymPropertiesAttr::get(
808 context, sym, fieldID, StringAttr::get(context,
"public")));
812 [](
auto &p,
auto &q) {
return p.getFieldID() < q.getFieldID(); });
813 return {hw::InnerSymAttr::get(context, props), sym};
820 if (
auto mod = dyn_cast<FModuleOp>(target.
getOp())) {
821 auto portIdx = target.
getPort();
822 assert(portIdx < mod.getNumPorts());
826 mod.setPortSymbolAttr(portIdx, attr);
831 if (
auto symOp = dyn_cast<hw::InnerSymbolOpInterface>(target.
getOp())) {
835 symOp.setInnerSymbolAttr(attr);
840 assert(0 &&
"target must be port of FModuleOp or InnerSymbol");
848 module = cast<FModuleLike>(target.getOp());
850 module = target.getOp()->getParentOfType<FModuleOp>();
854 return getNamespace(module);
863 auto mod = target.
isPort() ? dyn_cast<FModuleOp>(target.
getOp())
864 : target.
getOp()->getParentOfType<FModuleOp>();
866 "must be an operation inside an FModuleOp or port of FModuleOp");
867 return hw::InnerRefAttr::get(SymbolTable::getSymbolName(mod),
872std::pair<bool, std::optional<mlir::LocationAttr>>
874 StringAttr &locatorFilenameCache,
875 FileLineColLoc &fileLineColLocCache,
876 MLIRContext *context) {
878 if (!spelling.starts_with(
"@[") || !spelling.ends_with(
"]"))
879 return {
false, std::nullopt};
881 spelling = spelling.drop_front(2).drop_back(1);
885 auto decodeLocator = [&](StringRef input,
unsigned &resultLineNo,
886 unsigned &resultColNo) -> StringRef {
888 auto spaceLoc = input.find_last_of(
' ');
889 if (spaceLoc == StringRef::npos)
892 auto filename = input.take_front(spaceLoc);
893 auto lineAndColumn = input.drop_front(spaceLoc + 1);
897 StringRef lineStr, colStr;
898 std::tie(lineStr, colStr) = lineAndColumn.split(
':');
901 if (lineStr.getAsInteger(10, resultLineNo))
903 if (!colStr.empty()) {
904 if (colStr.front() !=
'{') {
905 if (colStr.getAsInteger(10, resultColNo))
909 if (colStr.drop_front().split(
',').first.getAsInteger(10, resultColNo))
917 unsigned lineNo = 0, columnNo = 0;
918 StringRef filename = decodeLocator(spelling, lineNo, columnNo);
919 if (filename.empty())
920 return {
false, std::nullopt};
925 return {
true, std::nullopt};
929 auto getFileLineColLoc = [&](StringRef filename,
unsigned lineNo,
930 unsigned columnNo) -> FileLineColLoc {
932 StringAttr filenameId = locatorFilenameCache;
933 if (filenameId.str() != filename) {
935 locatorFilenameCache = filenameId = StringAttr::get(context, filename);
939 return fileLineColLocCache =
940 FileLineColLoc::get(filenameId, lineNo, columnNo);
944 auto result = fileLineColLocCache;
945 if (result && result.getLine() == lineNo && result.getColumn() == columnNo)
948 return fileLineColLocCache =
949 FileLineColLoc::get(filenameId, lineNo, columnNo);
960 SmallVector<Location> extraLocs;
961 auto spaceLoc = filename.find_last_of(
' ');
962 while (spaceLoc != StringRef::npos) {
965 unsigned nextLineNo = 0, nextColumnNo = 0;
967 decodeLocator(filename.take_front(spaceLoc), nextLineNo, nextColumnNo);
970 if (nextFilename.empty())
976 getFileLineColLoc(filename.drop_front(spaceLoc + 1), lineNo, columnNo);
977 extraLocs.push_back(loc);
978 filename = nextFilename;
980 columnNo = nextColumnNo;
981 spaceLoc = filename.find_last_of(
' ');
984 mlir::LocationAttr result = getFileLineColLoc(filename, lineNo, columnNo);
985 if (!extraLocs.empty()) {
986 extraLocs.push_back(result);
987 std::reverse(extraLocs.begin(), extraLocs.end());
988 result = FusedLoc::get(context, extraLocs);
990 return {
true, result};
997 Type type, std::optional<Location> loc,
998 llvm::function_ref<hw::TypeAliasType(Type, BaseTypeAliasType, Location)>
1000 auto firType = type_dyn_cast<FIRRTLBaseType>(type);
1006 if (BaseTypeAliasType aliasType = dyn_cast<BaseTypeAliasType>(firType)) {
1008 loc = UnknownLoc::get(type.getContext());
1009 type =
lowerType(aliasType.getInnerType(), loc, getTypeDeclFn);
1010 return getTypeDeclFn(type, aliasType, *loc);
1013 firType = firType.getPassiveType();
1015 if (
auto bundle = type_dyn_cast<BundleType>(firType)) {
1016 mlir::SmallVector<hw::StructType::FieldInfo, 8> hwfields;
1017 for (
auto element : bundle) {
1018 Type etype =
lowerType(element.type, loc, getTypeDeclFn);
1021 hwfields.push_back(hw::StructType::FieldInfo{element.name, etype});
1023 return hw::StructType::get(type.getContext(), hwfields);
1025 if (
auto vec = type_dyn_cast<FVectorType>(firType)) {
1026 auto elemTy =
lowerType(vec.getElementType(), loc, getTypeDeclFn);
1029 return hw::ArrayType::get(elemTy, vec.getNumElements());
1031 if (
auto fenum = type_dyn_cast<FEnumType>(firType)) {
1032 mlir::SmallVector<hw::UnionType::FieldInfo, 8> hwfields;
1033 SmallVector<Attribute> names;
1035 for (
auto element : fenum) {
1036 Type etype =
lowerType(element.type, loc, getTypeDeclFn);
1039 hwfields.push_back(hw::UnionType::FieldInfo{element.name, etype, 0});
1040 names.push_back(element.name);
1041 if (!isa<UIntType>(element.type) ||
1042 element.type.getBitWidthOrSentinel() != 0)
1045 auto tagTy = hw::EnumType::get(type.getContext(),
1046 ArrayAttr::get(type.getContext(), names));
1049 auto bodyTy = hw::UnionType::get(type.getContext(), hwfields);
1050 hw::StructType::FieldInfo fields[2] = {
1051 {StringAttr::get(type.getContext(),
"tag"), tagTy},
1052 {StringAttr::get(type.getContext(),
"body"), bodyTy}};
1053 return hw::StructType::get(type.getContext(), fields);
1055 if (type_isa<ClockType>(firType))
1056 return seq::ClockType::get(firType.getContext());
1058 auto width = firType.getBitWidthOrSentinel();
1060 return IntegerType::get(type.getContext(), width);
1068 size_t e = std::min(a.size(), b.size());
1075 auto sep = llvm::sys::path::get_separator();
1076 while (!a.empty() && !a.ends_with(sep))
1081 mlir::ImplicitLocOpBuilder &builderOM) {
1083 auto *context = op->getContext();
1084 auto id = DistinctAttr::create(UnitAttr::get(context));
1085 TargetKind kind = TargetKind::Reference;
1088 NamedAttrList fields;
1089 fields.append(
"id",
id);
1090 fields.append(
"class", StringAttr::get(context,
"circt.tracker"));
1092 fields.append(
"circt.nonlocal", mlir::FlatSymbolRefAttr::get(nla));
1096 if (isa<InstanceOp, FModuleLike>(op))
1097 kind = TargetKind::Instance;
1101 return builderOM.create<PathOp>(kind, id);
assert(baseType &&"element must be base type")
MlirType uint64_t numElements
static void getDeclName(Value value, SmallString< 64 > &string, bool nameSafe)
Get the string name of a value which is a direct child of a declaration op.
static Value lookThroughWires(Value value)
Trace a value through wires to its original definition.
This class represents a reference to a specific field or element of an aggregate value.
unsigned getFieldID() const
Get the field ID of this FieldRef, which is a unique identifier mapped to a specific field in a bundl...
Value getValue() const
Get the Value which created this location.
This class provides a read-only projection over the MLIR attributes that represent a set of annotatio...
bool applyToOperation(Operation *op) const
Store the annotations in this set in an operation's annotations attribute, overwriting any existing a...
void addAnnotations(ArrayRef< Annotation > annotations)
Add more annotations to this annotation set.
bool isConst()
Returns true if this is a 'const' type that can only hold compile-time constant values.
This class implements the same functionality as TypeSwitch except that it uses firrtl::type_dyn_cast ...
FIRRTLTypeSwitch< T, ResultT > & Case(CallableT &&caseFn)
Add a case on the given type.
This is the common base class between SIntType and UIntType.
IntType getConstType(bool isConst)
Return a 'const' or non-'const' version of this type.
The target of an inner symbol, the entity the symbol is a handle for.
auto getField() const
Return the target's fieldID.
auto getPort() const
Return the target's port, if valid. Check "isPort()".
bool isPort() const
Return if this targets a port.
Operation * getOp() const
Return the target's base operation. For ports, this is the module.
llvm::function_ref< hw::InnerSymbolNamespace &(FModuleLike mod)> GetNamespaceCallback
FieldRef getFieldRefForTarget(const hw::InnerSymTarget &ist)
Get FieldRef pointing to the specified inner symbol target, which must be valid.
FieldRef getDeltaRef(Value value, bool lookThroughCasts=false)
Get the delta indexing from a value, as a FieldRef.
FIRRTLBaseType getBaseType(Type type)
If it is a base type, return it as is.
FieldRef getFieldRefFromValue(Value value, bool lookThroughCasts=false)
Get the FieldRef from a value.
mlir::TypedValue< FIRRTLBaseType > FIRRTLBaseValue
void walkGroundTypes(FIRRTLType firrtlType, llvm::function_ref< void(uint64_t, FIRRTLBaseType, bool)> fn)
Walk leaf ground types in the firrtlType and apply the function fn.
PathOp createPathRef(Operation *op, hw::HierPathOp nla, mlir::ImplicitLocOpBuilder &builderOM)
Add the tracker annotation to the op and get a PathOp to the op.
IntegerAttr getIntAttr(Type type, const APInt &value)
Utiility for generating a constant attribute.
std::pair< bool, std::optional< mlir::LocationAttr > > maybeStringToLocation(llvm::StringRef spelling, bool skipParsing, mlir::StringAttr &locatorFilenameCache, FileLineColLoc &fileLineColLocCache, MLIRContext *context)
std::pair< hw::InnerSymAttr, StringAttr > getOrAddInnerSym(MLIRContext *context, hw::InnerSymAttr attr, uint64_t fieldID, llvm::function_ref< hw::InnerSymbolNamespace &()> getNamespace)
Ensure that the the InnerSymAttr has a symbol on the field specified.
hw::InnerRefAttr getInnerRefTo(const hw::InnerSymTarget &target, GetNamespaceCallback getNamespace)
Obtain an inner reference to the target (operation or port), adding an inner symbol as necessary.
PropAssignOp getPropertyAssignment(FIRRTLPropertyValue value)
Return the single assignment to a Property value.
Value getModuleScopedDriver(Value val, bool lookThroughWires, bool lookThroughNodes, bool lookThroughCasts)
Return the value that drives another FIRRTL value within module scope.
Value getDriverFromConnect(Value val)
Return the module-scoped driver of a value only looking through one connect.
Value getValueByFieldID(ImplicitLocOpBuilder builder, Value value, unsigned fieldID)
This gets the value targeted by a field id.
std::pair< std::string, bool > getFieldName(const FieldRef &fieldRef, bool nameSafe=false)
Get a string identifier representing the FieldRef.
llvm::function_ref< bool(const FieldRef &dst, const FieldRef &src)> WalkDriverCallback
Walk all the drivers of a value, passing in the connect operations drive the value.
mlir::TypedValue< PropertyType > FIRRTLPropertyValue
Type lowerType(Type type, std::optional< Location > loc={}, llvm::function_ref< hw::TypeAliasType(Type, BaseTypeAliasType, Location)> getTypeDeclFn={})
Given a type, return the corresponding lowered type for the HW dialect.
hw::InnerSymTarget getTargetFor(FieldRef ref)
Return the inner sym target for the specified value and fieldID.
bool areTypesConstCastable(FIRRTLType destType, FIRRTLType srcType, bool srcOuterTypeIsConst=false)
Returns whether the srcType can be const-casted to the destType.
bool walkDrivers(FIRRTLBaseValue value, bool lookThroughWires, bool lookThroughNodes, bool lookThroughCasts, WalkDriverCallback callback)
IntegerAttr getIntOnesAttr(Type type)
Utility for generating a constant all ones attribute.
void emitConnect(OpBuilder &builder, Location loc, Value lhs, Value rhs)
Emit a connect between two values.
void makeCommonPrefix(SmallString< 64 > &a, StringRef b)
Truncate a to the common prefix of a and b.
IntegerAttr getIntZerosAttr(Type type)
Utility for generating a constant zero attribute.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.