18 #include "mlir/IR/ImplicitLocOpBuilder.h"
19 #include "llvm/ADT/TypeSwitch.h"
21 using namespace circt;
22 using namespace firrtl;
26 ImplicitLocOpBuilder locBuilder(loc,
builder.getInsertionBlock(),
29 builder.restoreInsertionPoint(locBuilder.saveInsertionPoint());
35 auto dstFType = type_cast<FIRRTLType>(dst.getType());
36 auto srcFType = type_cast<FIRRTLType>(src.getType());
37 auto dstType = type_dyn_cast<FIRRTLBaseType>(dstFType);
38 auto srcType = type_dyn_cast<FIRRTLBaseType>(srcFType);
42 if (type_isa<RefType>(dstFType)) {
43 if (dstFType != srcFType)
44 src =
builder.create<RefCastOp>(dstFType, src);
45 builder.create<RefDefineOp>(dst, src);
46 }
else if (type_isa<PropertyType>(dstFType) &&
47 type_isa<PropertyType>(srcFType)) {
49 builder.create<PropAssignOp>(dst, src);
52 builder.create<ConnectOp>(dst, src);
58 if (isa<AnalogType>(dstType)) {
59 builder.create<AttachOp>(ArrayRef{dst, src});
64 if (dstType == srcType && dstType.isPassive() &&
65 !dstType.hasUninferredWidth()) {
66 builder.create<StrictConnectOp>(dst, src);
70 if (
auto dstBundle = type_dyn_cast<BundleType>(dstType)) {
75 auto srcBundle = type_dyn_cast<BundleType>(srcType);
76 if (!srcBundle ||
numElements != srcBundle.getNumElements()) {
77 builder.create<ConnectOp>(dst, src);
81 auto dstField =
builder.create<SubfieldOp>(dst, i);
82 auto srcField =
builder.create<SubfieldOp>(src, i);
83 if (dstBundle.getElement(i).isFlip)
84 std::swap(dstField, srcField);
90 if (
auto dstVector = type_dyn_cast<FVectorType>(dstType)) {
95 auto srcVector = type_dyn_cast<FVectorType>(srcType);
96 if (!srcVector ||
numElements != srcVector.getNumElements()) {
97 builder.create<ConnectOp>(dst, src);
101 auto dstField =
builder.create<SubindexOp>(dst, i);
102 auto srcField =
builder.create<SubindexOp>(src, i);
108 if ((dstType.hasUninferredReset() || srcType.hasUninferredReset()) &&
109 dstType != srcType) {
110 srcType = dstType.getConstType(srcType.isConst());
111 src =
builder.create<UninferredResetCastOp>(srcType, src);
115 auto dstWidth = dstType.getBitWidthOrSentinel();
116 auto srcWidth = srcType.getBitWidthOrSentinel();
117 if (dstWidth < 0 || srcWidth < 0) {
124 if (dstType != srcType && dstType.getWidthlessType() != srcType &&
126 src =
builder.create<ConstCastOp>(dstType.getWidthlessType(), src);
129 builder.create<ConnectOp>(dst, src);
134 if (dstWidth < srcWidth) {
137 type_cast<IntType>(dstType).
getConstType(srcType.isConst());
138 bool isSignedDest = tmpType.
isSigned();
141 UIntType::get(dstType.getContext(), dstWidth, srcType.isConst());
142 src =
builder.create<TailPrimOp>(tmpType, src, srcWidth - dstWidth);
145 src =
builder.create<AsSIntPrimOp>(
146 dstType.getConstType(tmpType.
isConst()), src);
147 }
else if (srcWidth < dstWidth) {
149 src =
builder.create<PadPrimOp>(src, dstWidth);
152 if (
auto srcType = type_cast<FIRRTLBaseType>(src.getType());
153 srcType && dstType != srcType &&
155 src =
builder.create<ConstCastOp>(dstType, src);
160 if (dstType == src.getType() && dstType.isPassive() &&
161 !dstType.hasUninferredWidth()) {
162 builder.create<StrictConnectOp>(dst, src);
164 builder.create<ConnectOp>(dst, src);
168 auto intType = type_cast<IntType>(type);
169 assert((!intType.hasWidth() ||
170 (
unsigned)intType.getWidthOrSentinel() == value.getBitWidth()) &&
171 "value / type width mismatch");
173 intType.isSigned() ? IntegerType::Signed : IntegerType::Unsigned;
182 int32_t
width = abs(type_cast<IntType>(type).getWidthOrSentinel());
189 int32_t
width = abs(type_cast<IntType>(type).getWidthOrSentinel());
196 for (
auto *user : value.getUsers())
197 if (
auto propassign = dyn_cast<PropAssignOp>(user))
198 if (propassign.getDest() == value)
213 for (
auto *user : val.getUsers()) {
214 if (
auto connect = dyn_cast<FConnectLike>(user)) {
224 bool lookThroughNodes,
225 bool lookThroughCasts) {
230 auto updateVal = [&](Value thisVal) {
231 for (
auto *user : thisVal.getUsers()) {
232 if (
auto connect = dyn_cast<FConnectLike>(user)) {
245 if (
auto blockArg = dyn_cast<BlockArgument>(val)) {
246 FModuleOp op = cast<FModuleOp>(val.getParentBlock()->getParentOp());
247 auto direction = op.getPortDirection(blockArg.getArgNumber());
255 auto *op = val.getDefiningOp();
258 if (
auto inst = dyn_cast<InstanceOp>(op)) {
259 auto resultNo = cast<OpResult>(val).getResultNumber();
262 return inst.getResult(resultNo);
269 updateVal(op->getResult(0));
274 if (lookThroughNodes && isa<NodeOp>(op)) {
275 val = cast<NodeOp>(op).getInput();
279 if (lookThroughCasts &&
280 isa<AsUIntPrimOp, AsSIntPrimOp, AsClockPrimOp, AsAsyncResetPrimOp>(
282 val = op->getOperand(0);
287 if (isa<PadPrimOp, TailPrimOp>(op)) {
288 val = op->getOperand(0);
303 bool lookThroughNodes,
bool lookThroughCasts,
307 assert(value.getType().isPassive() &&
"this code was not tested with flips");
318 struct StackElement {
320 : dst(dst), src(src), current(current), it(current.user_begin()),
333 Value::user_iterator it;
337 SmallVector<StackElement> workStack;
344 workStack.emplace_back(dst, src, value, src.
getFieldID());
350 auto fieldRef = original;
358 auto val = fieldRef.getValue();
361 if (
auto blockArg = dyn_cast<BlockArgument>(val)) {
362 auto *parent = val.getParentBlock()->getParentOp();
363 auto module = cast<FModuleLike>(parent);
364 auto direction = module.getPortDirection(blockArg.getArgNumber());
367 if (!callback(original, fieldRef))
371 addToWorklist(original, fieldRef);
375 auto *op = val.getDefiningOp();
378 if (
auto inst = dyn_cast<InstanceOp>(op)) {
379 auto resultNo = cast<OpResult>(val).getResultNumber();
382 if (!callback(original, fieldRef))
386 addToWorklist(original, fieldRef);
392 addToWorklist(original, fieldRef);
397 if (lookThroughNodes && isa<NodeOp>(op)) {
398 auto input = cast<NodeOp>(op).getInput();
400 fieldRef = next.getSubField(fieldRef.getFieldID());
405 if (lookThroughCasts &&
406 isa<AsUIntPrimOp, AsSIntPrimOp, AsClockPrimOp, AsAsyncResetPrimOp>(
408 auto input = op->getOperand(0);
410 fieldRef = next.getSubField(fieldRef.getFieldID());
415 if (isa<PadPrimOp, TailPrimOp>(op)) {
416 auto input = op->getOperand(0);
418 fieldRef = next.getSubField(fieldRef.getFieldID());
427 if (!callback(original, fieldRef))
435 if (workStack.empty())
437 auto &back = workStack.back();
438 auto current = back.current;
440 if (back.it == current.user_end()) {
441 workStack.pop_back();
447 auto *user = *back.it++;
448 auto fieldID = back.fieldID;
450 if (
auto subfield = dyn_cast<SubfieldOp>(user)) {
451 BundleType bundleType = subfield.getInput().getType();
452 auto index = subfield.getFieldIndex();
453 auto subID = bundleType.getFieldID(index);
455 if (fieldID && index != bundleType.getIndexForFieldID(fieldID))
457 auto subRef = fieldRef.getSubField(subID);
458 auto subOriginal = original.getSubField(subID);
459 auto value = subfield.getResult();
460 workStack.emplace_back(subOriginal, subRef, value, fieldID - subID);
461 }
else if (
auto subindex = dyn_cast<SubindexOp>(user)) {
462 FVectorType vectorType = subindex.getInput().getType();
463 auto index = subindex.getIndex();
464 auto subID = vectorType.getFieldID(index);
466 if (fieldID && index != vectorType.getIndexForFieldID(fieldID))
468 auto subRef = fieldRef.getSubField(subID);
469 auto subOriginal = original.getSubField(subID);
470 auto value = subindex.getResult();
471 workStack.emplace_back(subOriginal, subRef, value, fieldID - subID);
472 }
else if (
auto connect = dyn_cast<FConnectLike>(user)) {
474 if (
connect.getDest() != current)
492 if (LLVM_UNLIKELY(!value))
496 auto *op = value.getDefiningOp();
503 return TypeSwitch<Operation *, FieldRef>(op)
504 .Case<RefCastOp, ConstCastOp, UninferredResetCastOp>(
505 [lookThroughCasts](
auto op) {
506 if (!lookThroughCasts)
510 .Case<SubfieldOp, OpenSubfieldOp, SubindexOp, OpenSubindexOp, RefSubOp,
512 [](
auto subOp) {
return subOp.getAccessedField(); })
517 bool lookThroughCasts) {
518 if (LLVM_UNLIKELY(!value))
524 auto deltaRef =
getDeltaRef(value, lookThroughCasts);
528 id = deltaRef.getSubField(
id).getFieldID();
530 value = deltaRef.getValue();
535 static void getDeclName(Value value, SmallString<64> &
string,
bool nameSafe) {
538 if (
auto arg = dyn_cast<BlockArgument>(value)) {
540 auto *op = arg.getOwner()->getParentOp();
541 TypeSwitch<Operation *>(op).Case<FModuleOp, ClassOp>([&](
auto op) {
542 auto name = cast<StringAttr>(op.getPortNames()[arg.getArgNumber()]);
543 string += name.getValue();
548 auto *op = value.getDefiningOp();
549 TypeSwitch<Operation *>(op)
550 .Case<ObjectOp>([&](ObjectOp op) {
551 string += op.getInstanceName();
554 .Case<InstanceOp, MemOp>([&](
auto op) {
555 string += op.getName();
556 string += nameSafe ?
"_" :
".";
557 string += op.getPortName(cast<OpResult>(value).getResultNumber())
561 .Case<FNamableOp>([&](
auto op) {
562 string += op.getName();
565 .Case<mlir::UnrealizedConversionCastOp>(
566 [&](mlir::UnrealizedConversionCastOp cast) {
568 if (cast.getNumResults() == 1 && cast.getNumOperands() == 1 &&
569 cast.getResult(0).getType() == cast.getOperand(0).getType()) {
570 value = cast.getInputs()[0];
585 std::pair<std::string, bool>
587 SmallString<64> name;
590 bool rootKnown = !name.empty();
592 auto type = value.getType();
596 if (
auto refTy = type_dyn_cast<RefType>(type))
597 type = refTy.getType();
599 if (
auto bundleType = type_dyn_cast<BundleType>(type)) {
600 auto index = bundleType.getIndexForFieldID(localID);
602 auto &element = bundleType.getElements()[index];
604 name += nameSafe ?
"_" :
".";
605 name += element.name.getValue();
608 localID = localID - bundleType.getFieldID(index);
609 }
else if (
auto bundleType = type_dyn_cast<OpenBundleType>(type)) {
610 auto index = bundleType.getIndexForFieldID(localID);
612 auto &element = bundleType.getElements()[index];
614 name += nameSafe ?
"_" :
".";
615 name += element.name.getValue();
618 localID = localID - bundleType.getFieldID(index);
619 }
else if (
auto vecType = type_dyn_cast<FVectorType>(type)) {
620 auto index = vecType.getIndexForFieldID(localID);
621 name += nameSafe ?
"_" :
"[";
622 name += std::to_string(index);
626 type = vecType.getElementType();
627 localID = localID - vecType.getFieldID(index);
628 }
else if (
auto vecType = type_dyn_cast<OpenVectorType>(type)) {
629 auto index = vecType.getIndexForFieldID(localID);
630 name += nameSafe ?
"_" :
"[";
631 name += std::to_string(index);
635 type = vecType.getElementType();
636 localID = localID - vecType.getFieldID(index);
637 }
else if (
auto enumType = type_dyn_cast<FEnumType>(type)) {
638 auto index = enumType.getIndexForFieldID(localID);
639 auto &element = enumType.getElements()[index];
640 name += nameSafe ?
"_" :
".";
641 name += element.name.getValue();
643 localID = localID - enumType.getFieldID(index);
644 }
else if (
auto classType = type_dyn_cast<ClassType>(type)) {
645 auto index = classType.getIndexForFieldID(localID);
646 auto &element = classType.getElement(index);
647 name += nameSafe ?
"_" :
".";
648 name += element.name.getValue();
650 localID = localID - classType.getFieldID(index);
656 llvm_unreachable(
"unsupported type");
660 return {name.str().str(), rootKnown};
668 Value value,
unsigned fieldID) {
670 while (fieldID != 0) {
672 .
Case<BundleType, OpenBundleType>([&](
auto bundle) {
673 auto index = bundle.getIndexForFieldID(fieldID);
674 value =
builder.create<SubfieldOp>(value, index);
675 fieldID -= bundle.getFieldID(index);
677 .Case<FVectorType, OpenVectorType>([&](
auto vector) {
678 auto index = vector.getIndexForFieldID(fieldID);
679 value =
builder.create<SubindexOp>(value, index);
680 fieldID -= vector.getFieldID(index);
682 .Case<RefType>([&](
auto reftype) {
684 .template Case<BundleType, FVectorType>([&](
auto type) {
685 auto index = type.getIndexForFieldID(fieldID);
686 value =
builder.create<RefSubOp>(value, index);
687 fieldID -= type.getFieldID(index);
689 .Default([&](
auto _) {
690 llvm::report_fatal_error(
691 "unrecognized type for indexing through with fieldID");
695 .Default([&](
auto _) {
696 llvm::report_fatal_error(
697 "unrecognized type for indexing through with fieldID");
717 return fn(0, type,
false);
719 uint64_t fieldID = 0;
720 auto recurse = [&](
auto &&f,
FIRRTLBaseType type,
bool isFlip) ->
void {
722 .
Case<BundleType>([&](BundleType bundle) {
723 for (
size_t i = 0, e = bundle.getNumElements(); i < e; ++i) {
725 f(f, bundle.getElementType(i),
726 isFlip ^ bundle.getElement(i).isFlip);
729 .
template Case<FVectorType>([&](FVectorType vector) {
730 for (
size_t i = 0, e = vector.getNumElements(); i < e; ++i) {
732 f(f, vector.getElementType(), isFlip);
735 .
template Case<FEnumType>([&](FEnumType fenum) {
736 for (
size_t i = 0, e = fenum.getNumElements(); i < e; ++i) {
738 f(f, fenum.getElementType(i), isFlip);
742 assert(groundType.isGround() &&
743 "only ground types are expected here");
744 fn(fieldID, groundType, isFlip);
747 recurse(recurse, type,
false);
754 if (
auto arg = dyn_cast<BlockArgument>(root)) {
755 auto mod = cast<FModuleLike>(arg.getOwner()->getParentOp());
763 MLIRContext *context, hw::InnerSymAttr attr, uint64_t fieldID,
765 SmallVector<hw::InnerSymPropertiesAttr> props;
768 if (
auto sym = attr.getSymIfExists(fieldID))
770 llvm::append_range(props, attr.getProps());
780 [](
auto &p,
auto &q) {
return p.getFieldID() < q.getFieldID(); });
788 if (
auto mod = dyn_cast<FModuleOp>(target.
getOp())) {
789 auto portIdx = target.
getPort();
790 assert(portIdx < mod.getNumPorts());
794 mod.setPortSymbolsAttr(portIdx, attr);
799 if (
auto symOp = dyn_cast<hw::InnerSymbolOpInterface>(target.
getOp())) {
803 symOp.setInnerSymbolAttr(attr);
808 assert(0 &&
"target must be port of FModuleOp or InnerSymbol");
816 module = cast<FModuleLike>(target.
getOp());
818 module = target.
getOp()->getParentOfType<FModuleOp>();
822 return getNamespace(module);
831 auto mod = target.
isPort() ? dyn_cast<FModuleOp>(target.
getOp())
832 : target.
getOp()->getParentOfType<FModuleOp>();
834 "must be an operation inside an FModuleOp or port of FModuleOp");
840 std::pair<bool, std::optional<mlir::LocationAttr>>
842 StringAttr &locatorFilenameCache,
843 FileLineColLoc &fileLineColLocCache,
844 MLIRContext *context) {
846 if (!spelling.starts_with(
"@[") || !spelling.ends_with(
"]"))
847 return {
false, std::nullopt};
849 spelling = spelling.drop_front(2).drop_back(1);
853 auto decodeLocator = [&](StringRef input,
unsigned &resultLineNo,
854 unsigned &resultColNo) -> StringRef {
856 auto spaceLoc = input.find_last_of(
' ');
857 if (spaceLoc == StringRef::npos)
860 auto filename = input.take_front(spaceLoc);
861 auto lineAndColumn = input.drop_front(spaceLoc + 1);
865 StringRef lineStr, colStr;
866 std::tie(lineStr, colStr) = lineAndColumn.split(
':');
869 if (lineStr.getAsInteger(10, resultLineNo))
871 if (!colStr.empty()) {
872 if (colStr.front() !=
'{') {
873 if (colStr.getAsInteger(10, resultColNo))
877 if (colStr.drop_front().split(
',').first.getAsInteger(10, resultColNo))
885 unsigned lineNo = 0, columnNo = 0;
886 StringRef filename = decodeLocator(spelling, lineNo, columnNo);
887 if (filename.empty())
888 return {
false, std::nullopt};
893 return {
true, std::nullopt};
897 auto getFileLineColLoc = [&](StringRef filename,
unsigned lineNo,
898 unsigned columnNo) -> FileLineColLoc {
900 StringAttr filenameId = locatorFilenameCache;
901 if (filenameId.str() != filename) {
903 locatorFilenameCache = filenameId =
StringAttr::get(context, filename);
907 return fileLineColLocCache =
912 auto result = fileLineColLocCache;
913 if (result && result.getLine() == lineNo && result.getColumn() == columnNo)
916 return fileLineColLocCache =
928 SmallVector<Location> extraLocs;
929 auto spaceLoc = filename.find_last_of(
' ');
930 while (spaceLoc != StringRef::npos) {
933 unsigned nextLineNo = 0, nextColumnNo = 0;
935 decodeLocator(filename.take_front(spaceLoc), nextLineNo, nextColumnNo);
938 if (nextFilename.empty())
944 getFileLineColLoc(filename.drop_front(spaceLoc + 1), lineNo, columnNo);
945 extraLocs.push_back(loc);
946 filename = nextFilename;
948 columnNo = nextColumnNo;
949 spaceLoc = filename.find_last_of(
' ');
952 mlir::LocationAttr result = getFileLineColLoc(filename, lineNo, columnNo);
953 if (!extraLocs.empty()) {
954 extraLocs.push_back(result);
955 std::reverse(extraLocs.begin(), extraLocs.end());
958 return {
true, result};
965 Type type, std::optional<Location> loc,
966 llvm::function_ref<hw::TypeAliasType(Type, BaseTypeAliasType, Location)>
968 auto firType = type_dyn_cast<FIRRTLBaseType>(type);
974 if (BaseTypeAliasType aliasType = dyn_cast<BaseTypeAliasType>(firType)) {
977 type =
lowerType(aliasType.getInnerType(), loc, getTypeDeclFn);
978 return getTypeDeclFn(type, aliasType, *loc);
981 firType = firType.getPassiveType();
983 if (
auto bundle = type_dyn_cast<BundleType>(firType)) {
984 mlir::SmallVector<hw::StructType::FieldInfo, 8> hwfields;
985 for (
auto element : bundle) {
986 Type etype =
lowerType(element.type, loc, getTypeDeclFn);
989 hwfields.push_back(hw::StructType::FieldInfo{element.name, etype});
993 if (
auto vec = type_dyn_cast<FVectorType>(firType)) {
994 auto elemTy =
lowerType(vec.getElementType(), loc, getTypeDeclFn);
999 if (
auto fenum = type_dyn_cast<FEnumType>(firType)) {
1000 mlir::SmallVector<hw::UnionType::FieldInfo, 8> hwfields;
1001 SmallVector<Attribute> names;
1003 for (
auto element : fenum) {
1004 Type etype =
lowerType(element.type, loc, getTypeDeclFn);
1007 hwfields.push_back(hw::UnionType::FieldInfo{element.name, etype, 0});
1008 names.push_back(element.name);
1009 if (!isa<UIntType>(element.type) ||
1010 element.type.getBitWidthOrSentinel() != 0)
1018 hw::StructType::FieldInfo fields[2] = {
1023 if (type_isa<ClockType>(firType))
1026 auto width = firType.getBitWidthOrSentinel();
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.
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.
Operation * getOp() const
Return the target's base operation. For ports, this is the module.
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.
def connect(destination, source)
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
llvm::function_ref< hw::InnerSymbolNamespace &(FModuleLike mod)> GetNamespaceCallback
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.
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.
IntegerAttr getIntZerosAttr(Type type)
Utility for generating a constant zero attribute.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.