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 = RefCastOp::create(builder, dstFType, src);
46 RefDefineOp::create(builder, dst, src);
47 }
else if (type_isa<PropertyType>(dstFType) &&
48 type_isa<PropertyType>(srcFType)) {
50 PropAssignOp::create(builder, dst, src);
51 }
else if (type_isa<DomainType>(dstFType) &&
52 type_isa<DomainType>(srcFType)) {
53 DomainDefineOp::create(builder, dst, src);
56 ConnectOp::create(builder, dst, src);
62 if (isa<AnalogType>(dstType)) {
63 AttachOp::create(builder, ArrayRef{dst, src});
68 if (dstType == srcType && dstType.isPassive() &&
69 !dstType.hasUninferredWidth()) {
70 MatchingConnectOp::create(builder, dst, src);
74 if (
auto dstBundle = type_dyn_cast<BundleType>(dstType)) {
79 auto srcBundle = type_dyn_cast<BundleType>(srcType);
80 if (!srcBundle ||
numElements != srcBundle.getNumElements()) {
81 ConnectOp::create(builder, dst, src);
85 auto dstField = SubfieldOp::create(builder, dst, i);
86 auto srcField = SubfieldOp::create(builder, src, i);
87 if (dstBundle.getElement(i).isFlip)
88 std::swap(dstField, srcField);
94 if (
auto dstVector = type_dyn_cast<FVectorType>(dstType)) {
99 auto srcVector = type_dyn_cast<FVectorType>(srcType);
100 if (!srcVector ||
numElements != srcVector.getNumElements()) {
101 ConnectOp::create(builder, dst, src);
105 auto dstField = SubindexOp::create(builder, dst, i);
106 auto srcField = SubindexOp::create(builder, src, i);
112 if ((dstType.hasUninferredReset() || srcType.hasUninferredReset()) &&
113 dstType != srcType) {
114 srcType = dstType.getConstType(srcType.isConst());
115 src = UninferredResetCastOp::create(builder, srcType, src);
119 auto dstWidth = dstType.getBitWidthOrSentinel();
120 auto srcWidth = srcType.getBitWidthOrSentinel();
121 if (dstWidth < 0 || srcWidth < 0) {
128 if (dstType != srcType && dstType.getWidthlessType() != srcType &&
130 src = ConstCastOp::create(builder, dstType.getWidthlessType(), src);
133 ConnectOp::create(builder, dst, src);
138 if (dstWidth < srcWidth) {
141 type_cast<IntType>(dstType).
getConstType(srcType.isConst());
142 bool isSignedDest = tmpType.
isSigned();
145 UIntType::get(dstType.getContext(), dstWidth, srcType.isConst());
146 src = TailPrimOp::create(builder, tmpType, src, srcWidth - dstWidth);
149 src = AsSIntPrimOp::create(builder,
150 dstType.getConstType(tmpType.
isConst()), src);
151 }
else if (srcWidth < dstWidth) {
153 src = PadPrimOp::create(builder, src, dstWidth);
156 if (
auto srcType = type_cast<FIRRTLBaseType>(src.getType());
157 srcType && dstType != srcType &&
159 src = ConstCastOp::create(builder, dstType, src);
164 if (dstType == src.getType() && dstType.isPassive() &&
165 !dstType.hasUninferredWidth()) {
166 MatchingConnectOp::create(builder, dst, src);
168 ConnectOp::create(builder, dst, src);
172 auto intType = type_cast<IntType>(type);
173 assert((!intType.hasWidth() ||
174 (
unsigned)intType.getWidthOrSentinel() == value.getBitWidth()) &&
175 "value / type width mismatch");
177 intType.isSigned() ? IntegerType::Signed : IntegerType::Unsigned;
179 IntegerType::get(type.getContext(), value.getBitWidth(), intSign);
180 return IntegerAttr::get(attrType, value);
186 int32_t width = abs(type_cast<IntType>(type).getWidthOrSentinel());
193 int32_t width = abs(type_cast<IntType>(type).getWidthOrSentinel());
195 type, APInt(width, -1,
false,
true));
201 for (
auto *user : value.getUsers())
202 if (
auto propassign = dyn_cast<PropAssignOp>(user))
203 if (propassign.getDest() == value)
218 for (
auto *user : val.getUsers()) {
219 if (
auto connect = dyn_cast<FConnectLike>(user)) {
220 if (connect.getDest() != val)
222 return connect.getSrc();
229 bool lookThroughNodes,
230 bool lookThroughCasts) {
235 auto updateVal = [&](Value thisVal) {
236 for (
auto *user : thisVal.getUsers()) {
237 if (
auto connect = dyn_cast<FConnectLike>(user)) {
238 if (connect.getDest() != val)
240 val = connect.getSrc();
250 if (
auto blockArg = dyn_cast<BlockArgument>(val)) {
251 FModuleOp op = cast<FModuleOp>(val.getParentBlock()->getParentOp());
252 auto direction = op.getPortDirection(blockArg.getArgNumber());
254 if (direction == Direction::In)
260 auto *op = val.getDefiningOp();
263 if (
auto inst = dyn_cast<InstanceOp>(op)) {
264 auto resultNo = cast<OpResult>(val).getResultNumber();
266 if (inst.getPortDirection(resultNo) == Direction::Out)
267 return inst.getResult(resultNo);
274 updateVal(op->getResult(0));
279 if (lookThroughNodes && isa<NodeOp>(op)) {
280 val = cast<NodeOp>(op).getInput();
284 if (lookThroughCasts &&
285 isa<AsUIntPrimOp, AsSIntPrimOp, AsClockPrimOp, AsAsyncResetPrimOp>(
287 val = op->getOperand(0);
292 if (isa<PadPrimOp, TailPrimOp>(op)) {
293 val = op->getOperand(0);
308 bool lookThroughNodes,
bool lookThroughCasts,
312 assert(value.getType().isPassive() &&
"this code was not tested with flips");
323 struct StackElement {
325 : dst(dst), src(src), current(current), it(current.user_begin()),
338 Value::user_iterator it;
342 SmallVector<StackElement> workStack;
349 workStack.emplace_back(dst, src, value, src.
getFieldID());
355 auto fieldRef = original;
363 auto val = fieldRef.getValue();
366 if (
auto blockArg = dyn_cast<BlockArgument>(val)) {
367 auto *parent = val.getParentBlock()->getParentOp();
368 auto module = cast<FModuleLike>(parent);
369 auto direction =
module.getPortDirection(blockArg.getArgNumber());
371 if (direction == Direction::In) {
372 if (!callback(original, fieldRef))
376 addToWorklist(original, fieldRef);
380 auto *op = val.getDefiningOp();
383 if (
auto inst = dyn_cast<InstanceOp>(op)) {
384 auto resultNo = cast<OpResult>(val).getResultNumber();
386 if (inst.getPortDirection(resultNo) == Direction::Out) {
387 if (!callback(original, fieldRef))
391 addToWorklist(original, fieldRef);
397 addToWorklist(original, fieldRef);
402 if (lookThroughNodes && isa<NodeOp>(op)) {
403 auto input = cast<NodeOp>(op).getInput();
405 fieldRef = next.getSubField(fieldRef.getFieldID());
410 if (lookThroughCasts &&
411 isa<AsUIntPrimOp, AsSIntPrimOp, AsClockPrimOp, AsAsyncResetPrimOp>(
413 auto input = op->getOperand(0);
415 fieldRef = next.getSubField(fieldRef.getFieldID());
420 if (isa<PadPrimOp, TailPrimOp>(op)) {
421 auto input = op->getOperand(0);
423 fieldRef = next.getSubField(fieldRef.getFieldID());
432 if (!callback(original, fieldRef))
440 if (workStack.empty())
442 auto &back = workStack.back();
443 auto current = back.current;
445 if (back.it == current.user_end()) {
446 workStack.pop_back();
452 auto *user = *back.it++;
453 auto fieldID = back.fieldID;
455 if (
auto subfield = dyn_cast<SubfieldOp>(user)) {
456 BundleType bundleType = subfield.getInput().getType();
457 auto index = subfield.getFieldIndex();
458 auto subID = bundleType.getFieldID(index);
460 if (fieldID && index != bundleType.getIndexForFieldID(fieldID))
462 auto subRef = fieldRef.getSubField(subID);
463 auto subOriginal = original.getSubField(subID);
464 auto value = subfield.getResult();
467 workStack.emplace_back(subOriginal, subRef, value, 0);
470 workStack.emplace_back(subOriginal, subRef, value, fieldID - subID);
472 }
else if (
auto subindex = dyn_cast<SubindexOp>(user)) {
473 FVectorType vectorType = subindex.getInput().getType();
474 auto index = subindex.getIndex();
475 auto subID = vectorType.getFieldID(index);
477 if (fieldID && index != vectorType.getIndexForFieldID(fieldID))
479 auto subRef = fieldRef.getSubField(subID);
480 auto subOriginal = original.getSubField(subID);
481 auto value = subindex.getResult();
484 workStack.emplace_back(subOriginal, subRef, value, 0);
487 workStack.emplace_back(subOriginal, subRef, value, fieldID - subID);
489 }
else if (
auto connect = dyn_cast<FConnectLike>(user)) {
491 if (connect.getDest() != current)
509 if (LLVM_UNLIKELY(!value))
513 auto *op = value.getDefiningOp();
520 return TypeSwitch<Operation *, FieldRef>(op)
521 .Case<RefCastOp, ConstCastOp, UninferredResetCastOp>(
522 [lookThroughCasts](
auto op) {
523 if (!lookThroughCasts)
527 .Case<SubfieldOp, OpenSubfieldOp, SubindexOp, OpenSubindexOp, RefSubOp,
529 [](
auto subOp) {
return subOp.getAccessedField(); })
534 bool lookThroughCasts) {
535 if (LLVM_UNLIKELY(!value))
541 auto deltaRef =
getDeltaRef(value, lookThroughCasts);
545 id = deltaRef.getSubField(
id).getFieldID();
547 value = deltaRef.getValue();
552static void getDeclName(Value value, SmallString<64> &
string,
bool nameSafe) {
555 if (
auto arg = dyn_cast<BlockArgument>(value)) {
557 auto *op = arg.getOwner()->getParentOp();
558 TypeSwitch<Operation *>(op).Case<FModuleOp, ClassOp>([&](
auto op) {
559 auto name = cast<StringAttr>(op.getPortNames()[arg.getArgNumber()]);
560 string += name.getValue();
565 auto *op = value.getDefiningOp();
566 TypeSwitch<Operation *>(op)
567 .Case<ObjectOp>([&](ObjectOp op) {
568 string += op.getInstanceName();
571 .Case<InstanceOp, MemOp>([&](
auto op) {
572 string += op.getName();
573 string += nameSafe ?
"_" :
".";
574 string += op.getPortName(cast<OpResult>(value).getResultNumber());
577 .Case<FNamableOp>([&](
auto op) {
578 string += op.getName();
581 .Case<mlir::UnrealizedConversionCastOp>(
582 [&](mlir::UnrealizedConversionCastOp cast) {
584 if (cast.getNumResults() == 1 && cast.getNumOperands() == 1 &&
585 cast.getResult(0).getType() == cast.getOperand(0).getType()) {
586 value = cast.getInputs()[0];
601std::pair<std::string, bool>
603 SmallString<64> name;
606 bool rootKnown = !name.empty();
608 auto type = value.getType();
612 if (
auto refTy = type_dyn_cast<RefType>(type))
613 type = refTy.getType();
615 if (
auto bundleType = type_dyn_cast<BundleType>(type)) {
616 auto index = bundleType.getIndexForFieldID(localID);
618 auto &element = bundleType.getElements()[index];
620 name += nameSafe ?
"_" :
".";
621 name += element.name.getValue();
624 localID = localID - bundleType.getFieldID(index);
625 }
else if (
auto bundleType = type_dyn_cast<OpenBundleType>(type)) {
626 auto index = bundleType.getIndexForFieldID(localID);
628 auto &element = bundleType.getElements()[index];
630 name += nameSafe ?
"_" :
".";
631 name += element.name.getValue();
634 localID = localID - bundleType.getFieldID(index);
635 }
else if (
auto vecType = type_dyn_cast<FVectorType>(type)) {
636 auto index = vecType.getIndexForFieldID(localID);
637 name += nameSafe ?
"_" :
"[";
638 name += std::to_string(index);
642 type = vecType.getElementType();
643 localID = localID - vecType.getFieldID(index);
644 }
else if (
auto vecType = type_dyn_cast<OpenVectorType>(type)) {
645 auto index = vecType.getIndexForFieldID(localID);
646 name += nameSafe ?
"_" :
"[";
647 name += std::to_string(index);
651 type = vecType.getElementType();
652 localID = localID - vecType.getFieldID(index);
653 }
else if (
auto classType = type_dyn_cast<ClassType>(type)) {
654 auto index = classType.getIndexForFieldID(localID);
655 auto &element = classType.getElement(index);
656 name += nameSafe ?
"_" :
".";
657 name += element.name.getValue();
659 localID = localID - classType.getFieldID(index);
665 llvm_unreachable(
"unsupported type");
669 return {name.str().str(), rootKnown};
677 Value value,
unsigned fieldID) {
679 while (fieldID != 0) {
681 .
Case<BundleType, OpenBundleType>([&](
auto bundle) {
682 auto index = bundle.getIndexForFieldID(fieldID);
683 value = SubfieldOp::create(builder, value, index);
684 fieldID -= bundle.getFieldID(index);
686 .Case<FVectorType, OpenVectorType>([&](
auto vector) {
687 auto index = vector.getIndexForFieldID(fieldID);
688 value = SubindexOp::create(builder, value, index);
689 fieldID -= vector.getFieldID(index);
691 .Case<RefType>([&](
auto reftype) {
693 .template Case<BundleType, FVectorType>([&](
auto type) {
694 auto index = type.getIndexForFieldID(fieldID);
695 value = RefSubOp::create(builder, value, index);
696 fieldID -= type.getFieldID(index);
698 .Default([&](
auto _) {
699 llvm::report_fatal_error(
700 "unrecognized type for indexing through with fieldID");
704 .Default([&](
auto _) {
705 llvm::report_fatal_error(
706 "unrecognized type for indexing through with fieldID");
726 return fn(0, type,
false);
728 uint64_t fieldID = 0;
729 auto recurse = [&](
auto &&f,
FIRRTLBaseType type,
bool isFlip) ->
void {
731 .
Case<BundleType>([&](BundleType bundle) {
732 for (
size_t i = 0, e = bundle.getNumElements(); i < e; ++i) {
734 f(f, bundle.getElementType(i),
735 isFlip ^ bundle.getElement(i).isFlip);
738 .
template Case<FVectorType>([&](FVectorType vector) {
739 for (
size_t i = 0, e = vector.getNumElements(); i < e; ++i) {
741 f(f, vector.getElementType(), isFlip);
744 .
template Case<FEnumType>([&](FEnumType fenum) {
748 fn(fieldID, fenum, isFlip);
751 assert(groundType.isGround() &&
752 "only ground types are expected here");
753 fn(fieldID, groundType, isFlip);
756 recurse(recurse, type,
false);
763 if (
auto arg = dyn_cast<BlockArgument>(root)) {
764 auto mod = cast<FModuleLike>(arg.getOwner()->getParentOp());
775 return TypeSwitch<Operation *, FieldRef>(ist.
getOp())
776 .Case<FModuleOp>([&](
auto fmod) {
782 auto symOp = dyn_cast<hw::InnerSymbolOpInterface>(ist.
getOp());
783 assert(symOp && symOp.getTargetResultIndex() &&
784 (symOp.supportsPerFieldSymbols() || ist.
getField() == 0));
790 MLIRContext *context, hw::InnerSymAttr attr, uint64_t fieldID,
792 SmallVector<hw::InnerSymPropertiesAttr> props;
795 if (
auto sym = attr.getSymIfExists(fieldID))
797 llvm::append_range(props, attr.getProps());
801 auto sym = StringAttr::get(context, getNamespace().newName(
"sym"));
802 props.push_back(hw::InnerSymPropertiesAttr::get(
803 context, sym, fieldID, StringAttr::get(context,
"public")));
807 [](
auto &p,
auto &q) {
return p.getFieldID() < q.getFieldID(); });
808 return {hw::InnerSymAttr::get(context, props), sym};
815 if (
auto mod = dyn_cast<FModuleLike>(target.
getOp())) {
816 auto portIdx = target.
getPort();
817 assert(portIdx < mod.getNumPorts());
821 mod.setPortSymbolAttr(portIdx, attr);
826 if (
auto symOp = dyn_cast<hw::InnerSymbolOpInterface>(target.
getOp())) {
830 symOp.setInnerSymbolAttr(attr);
835 assert(0 &&
"target must be port of FModuleLike or InnerSymbol");
843 module = cast<FModuleLike>(target.getOp());
845 module = target.getOp()->getParentOfType<FModuleOp>();
849 return getNamespace(module);
858 auto mod = target.
isPort() ? dyn_cast<FModuleLike>(target.
getOp())
859 : target.
getOp()->getParentOfType<FModuleOp>();
861 "must be an operation inside an FModuleOp or port of FModuleLike");
862 return hw::InnerRefAttr::get(SymbolTable::getSymbolName(mod),
867std::pair<bool, std::optional<mlir::LocationAttr>>
869 StringAttr &locatorFilenameCache,
870 FileLineColLoc &fileLineColLocCache,
871 MLIRContext *context) {
873 if (!spelling.starts_with(
"@[") || !spelling.ends_with(
"]"))
874 return {
false, std::nullopt};
876 spelling = spelling.drop_front(2).drop_back(1);
880 auto decodeLocator = [&](StringRef input,
unsigned &resultLineNo,
881 unsigned &resultColNo) -> StringRef {
883 auto spaceLoc = input.find_last_of(
' ');
884 if (spaceLoc == StringRef::npos)
887 auto filename = input.take_front(spaceLoc);
888 auto lineAndColumn = input.drop_front(spaceLoc + 1);
892 StringRef lineStr, colStr;
893 std::tie(lineStr, colStr) = lineAndColumn.split(
':');
896 if (lineStr.getAsInteger(10, resultLineNo))
898 if (!colStr.empty()) {
899 if (colStr.front() !=
'{') {
900 if (colStr.getAsInteger(10, resultColNo))
904 if (colStr.drop_front().split(
',').first.getAsInteger(10, resultColNo))
912 unsigned lineNo = 0, columnNo = 0;
913 StringRef filename = decodeLocator(spelling, lineNo, columnNo);
914 if (filename.empty())
915 return {
false, std::nullopt};
920 return {
true, std::nullopt};
924 auto getFileLineColLoc = [&](StringRef filename,
unsigned lineNo,
925 unsigned columnNo) -> FileLineColLoc {
927 StringAttr filenameId = locatorFilenameCache;
928 if (filenameId.str() != filename) {
930 locatorFilenameCache = filenameId = StringAttr::get(context, filename);
934 return fileLineColLocCache =
935 FileLineColLoc::get(filenameId, lineNo, columnNo);
939 auto result = fileLineColLocCache;
940 if (result && result.getLine() == lineNo && result.getColumn() == columnNo)
943 return fileLineColLocCache =
944 FileLineColLoc::get(filenameId, lineNo, columnNo);
955 SmallVector<Location> extraLocs;
956 auto spaceLoc = filename.find_last_of(
' ');
957 while (spaceLoc != StringRef::npos) {
960 unsigned nextLineNo = 0, nextColumnNo = 0;
962 decodeLocator(filename.take_front(spaceLoc), nextLineNo, nextColumnNo);
965 if (nextFilename.empty())
971 getFileLineColLoc(filename.drop_front(spaceLoc + 1), lineNo, columnNo);
972 extraLocs.push_back(loc);
973 filename = nextFilename;
975 columnNo = nextColumnNo;
976 spaceLoc = filename.find_last_of(
' ');
979 mlir::LocationAttr result = getFileLineColLoc(filename, lineNo, columnNo);
980 if (!extraLocs.empty()) {
981 extraLocs.push_back(result);
982 std::reverse(extraLocs.begin(), extraLocs.end());
983 result = FusedLoc::get(context, extraLocs);
985 return {
true, result};
992 Type type, std::optional<Location> loc,
993 llvm::function_ref<hw::TypeAliasType(Type, BaseTypeAliasType, Location)>
995 auto firType = type_dyn_cast<FIRRTLBaseType>(type);
1001 if (BaseTypeAliasType aliasType = dyn_cast<BaseTypeAliasType>(firType)) {
1003 loc = UnknownLoc::get(type.getContext());
1004 type =
lowerType(aliasType.getInnerType(), loc, getTypeDeclFn);
1005 return getTypeDeclFn(type, aliasType, *loc);
1008 firType = firType.getPassiveType();
1010 if (
auto bundle = type_dyn_cast<BundleType>(firType)) {
1011 mlir::SmallVector<hw::StructType::FieldInfo, 8> hwfields;
1012 for (
auto element : bundle) {
1013 Type etype =
lowerType(element.type, loc, getTypeDeclFn);
1016 hwfields.push_back(hw::StructType::FieldInfo{element.name, etype});
1018 return hw::StructType::get(type.getContext(), hwfields);
1020 if (
auto vec = type_dyn_cast<FVectorType>(firType)) {
1021 auto elemTy =
lowerType(vec.getElementType(), loc, getTypeDeclFn);
1024 return hw::ArrayType::get(elemTy, vec.getNumElements());
1026 if (
auto fenum = type_dyn_cast<FEnumType>(firType)) {
1027 mlir::SmallVector<hw::UnionType::FieldInfo, 8> hwfields;
1029 for (
auto element : fenum) {
1030 Type etype =
lowerType(element.type, loc, getTypeDeclFn);
1033 hwfields.push_back(hw::UnionType::FieldInfo{element.name, etype, 0});
1034 if (element.type.getBitWidthOrSentinel() != 0)
1037 auto tagTy = IntegerType::get(type.getContext(), fenum.getTagWidth());
1040 auto bodyTy = hw::UnionType::get(type.getContext(), hwfields);
1041 hw::StructType::FieldInfo fields[2] = {
1042 {StringAttr::get(type.getContext(),
"tag"), tagTy},
1043 {StringAttr::get(type.getContext(),
"body"), bodyTy}};
1044 return hw::StructType::get(type.getContext(), fields);
1046 if (type_isa<ClockType>(firType))
1047 return seq::ClockType::get(firType.getContext());
1049 auto width = firType.getBitWidthOrSentinel();
1051 return IntegerType::get(type.getContext(), width);
1059 size_t e = std::min(a.size(), b.size());
1066 auto sep = llvm::sys::path::get_separator();
1067 while (!a.empty() && !a.ends_with(sep))
1072 mlir::ImplicitLocOpBuilder &builderOM) {
1074 auto *context = op->getContext();
1075 auto id = DistinctAttr::create(UnitAttr::get(context));
1076 TargetKind kind = TargetKind::Reference;
1079 NamedAttrList fields;
1080 fields.append(
"id",
id);
1081 fields.append(
"class", StringAttr::get(context,
"circt.tracker"));
1083 fields.append(
"circt.nonlocal", mlir::FlatSymbolRefAttr::get(nla));
1087 if (isa<InstanceOp, FModuleLike>(op))
1088 kind = TargetKind::Instance;
1092 return PathOp::create(builderOM, 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() const
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) const
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.