21 #include "mlir/IR/Operation.h"
22 #include "mlir/Interfaces/FunctionImplementation.h"
23 #include "llvm/ADT/TypeSwitch.h"
25 using namespace circt;
26 using namespace firrtl;
35 MLIRContext *context) {
36 if (annotations.empty())
38 SmallVector<Attribute> attrs;
39 attrs.reserve(annotations.size());
40 for (
auto anno : annotations)
41 attrs.push_back(anno.getAttr());
48 : annotations(ArrayAttr::
get(context, annotations)) {}
65 if (ports && !ports.empty())
80 if (
auto *op = v.getDefiningOp())
83 auto arg = dyn_cast<BlockArgument>(v);
84 auto module = cast<FModuleOp>(arg.getOwner()->getParentOp());
85 return forPort(module, arg.getArgNumber());
91 auto before = op->getAttrDictionary();
93 return op->getAttrDictionary() != before;
98 assert(portNo < portCount &&
"port index out of range.");
99 auto *context = op->getContext();
101 SmallVector<Attribute> portAnnotations;
102 if (!before || before.empty())
105 portAnnotations.append(before.begin(), before.end());
110 return before != after;
122 for (
auto annotation : *
this) {
123 if (annotation.getClassAttr() == className)
130 for (
auto annotation : *
this) {
131 if (annotation.getClass() == className)
195 return llvm::all_of(
annotations, [](Attribute attr) {
206 if (newAnnotations.empty())
209 SmallVector<Attribute> annotationVec;
210 annotationVec.reserve(
annotations.size() + newAnnotations.size());
212 for (
auto anno : newAnnotations)
213 annotationVec.push_back(anno.getDict());
218 if (newAnnotations.empty())
226 SmallVector<Attribute> annotationVec;
227 annotationVec.reserve(
annotations.size() + newAnnotations.size());
229 annotationVec.append(newAnnotations.begin(), newAnnotations.end());
242 SmallVector<Attribute> annotationVec;
243 annotationVec.reserve(
annotations.size() + newAnnotations.size());
245 annotationVec.append(newAnnotations.begin(), newAnnotations.end());
272 llvm::function_ref<
bool(
Annotation)> predicate) {
275 auto *it = annos.begin();
276 while (it != annos.end() && !predicate(
Annotation(*it)))
280 if (it == annos.end())
284 SmallVector<Attribute> filteredAnnos;
285 filteredAnnos.reserve(annos.size());
286 filteredAnnos.append(annos.begin(), it);
288 while (it != annos.end()) {
290 filteredAnnos.push_back(*it);
299 Operation *op, llvm::function_ref<
bool(
Annotation)> predicate) {
321 llvm::function_ref<
bool(
unsigned,
Annotation)> predicate) {
322 auto ports = dyn_cast_or_null<ArrayAttr>(module->getAttr(
"portAnnotations"));
323 if (!ports || ports.empty())
327 SmallVector<Attribute> newAnnos;
330 bool changed =
false;
331 for (
unsigned argNum = 0, argNumEnd = ports.size(); argNum < argNumEnd;
340 [&](
Annotation anno) {
return predicate(argNum, anno); });
346 module->setAttr(
"portAnnotations",
356 return cast<DictionaryAttr>(
attr);
362 if (
auto fieldID = getMember<IntegerAttr>(
"circt.fieldID"))
363 return fieldID.getInt();
369 return getDict().getAs<StringAttr>(
"class");
375 return classAttr.getValue();
386 auto [it, found] = mlir::impl::findAttrSorted(dict.begin(), dict.end(), name);
387 auto index = std::distance(dict.begin(), it);
389 SmallVector<NamedAttribute> attributes;
390 attributes.reserve(dict.size() + 1);
392 for (
auto field : dict.getValue().take_front(index))
393 attributes.push_back(field);
396 attributes.push_back(NamedAttribute(nameAttr, value));
398 for (
auto field : dict.getValue().drop_front(index + found))
399 attributes.push_back(field);
401 setDict(DictionaryAttr::getWithSorted(dict.getContext(), attributes));
406 SmallVector<NamedAttribute> attributes;
407 attributes.reserve(dict.size() - 1);
408 auto *i = dict.begin();
409 auto *e = dict.end();
410 while (i != e && i->getValue() != name)
411 attributes.push_back(*(i++));
416 attributes.append(++i, e);
418 setDict(DictionaryAttr::getWithSorted(dict.getContext(), attributes));
424 auto [it, found] = mlir::impl::findAttrSorted(dict.begin(), dict.end(), name);
425 auto index = std::distance(dict.begin(), it);
429 SmallVector<NamedAttribute> attributes;
430 attributes.reserve(dict.size() - 1);
432 for (
auto field : dict.getValue().take_front(index))
433 attributes.push_back(field);
435 for (
auto field : dict.getValue().drop_front(index + 1))
436 attributes.push_back(field);
438 setDict(DictionaryAttr::getWithSorted(dict.getContext(), attributes));
447 auto tpe = getMember<StringAttr>(
"type");
449 (tpe ==
"OMReferenceTarget" || tpe ==
"OMMemberReferenceTarget" ||
450 tpe ==
"OMMemberInstanceTarget");
460 return Annotation(this->getBase().getArray()[this->getIndex()]);
469 if (
auto module = llvm::dyn_cast<FModuleLike>(op))
471 return op->getParentOfType<FModuleLike>();
475 return TypeSwitch<AnnoTarget, AnnotationSet>(*
this)
477 [&](
auto target) {
return target.getAnnotations(); })
483 [&](
auto target) { target.setAnnotations(annotations); });
488 return TypeSwitch<AnnoTarget, Attribute>(*
this)
490 [&](
auto target) {
return target.getNLAReference(moduleNamespace); })
491 .Default([](
auto target) {
return Attribute(); });
495 return TypeSwitch<AnnoTarget, FIRRTLType>(*
this)
497 [](
auto target) {
return target.getType(); })
498 .Default([](
auto target) {
return FIRRTLType(); });
512 if (
auto module = llvm::dyn_cast<FModuleLike>(
getOp())) {
513 assert(module.getModuleNameAttr() &&
"invalid NLA reference");
519 return moduleNamespace;
526 if (
auto is = llvm::dyn_cast<hw::InnerSymbolOpInterface>(op)) {
527 auto result = is.getTargetResult();
530 return type_cast<FIRRTLType>(result.getType());
533 if (op->getNumResults() != 1)
535 return type_cast<FIRRTLType>(op->getResult(0).getType());
545 if (
auto memOp = llvm::dyn_cast<MemOp>(
getOp()))
547 if (
auto moduleOp = llvm::dyn_cast<FModuleLike>(
getOp()))
549 llvm_unreachable(
"unknown port target");
554 if (
auto memOp = llvm::dyn_cast<MemOp>(
getOp()))
556 else if (
auto moduleOp = llvm::dyn_cast<FModuleLike>(
getOp()))
559 llvm_unreachable(
"unknown port target");
564 auto module = llvm::dyn_cast<FModuleLike>(
getOp());
569 return moduleNamespace;
575 if (
auto module = llvm::dyn_cast<FModuleLike>(op))
576 return type_cast<FIRRTLType>(module.getPortType(
getPortNo()));
577 if (llvm::isa<MemOp, InstanceOp>(op))
579 llvm_unreachable(
"unknown operation kind");
590 return type ==
"OMID" || type ==
"OMReference" || type ==
"OMBigInt" ||
591 type ==
"OMLong" || type ==
"OMString" || type ==
"OMDouble" ||
592 type ==
"OMBigDecimal" || type ==
"OMDeleted";
608 auto diag = emitError(mod->getLoc())
610 << dut.getModuleName()
611 <<
"' also had such an annotation (this should "
613 diag.attachNote(dut.getLoc()) <<
"the first DUT was found here";
assert(baseType &&"element must be base type")
static bool applyToPort(AnnotationSet annos, Operation *op, size_t portCount, size_t portNo)
static AnnotationSet forPort(Operation *op, size_t portNo)
static ArrayAttr getAnnotationsFrom(Operation *op)
Annotation operator*() const
This class provides a read-only projection over the MLIR attributes that represent a set of annotatio...
bool hasDontTouch() const
firrtl.transforms.DontTouchAnnotation
bool hasAnnotationImpl(StringAttr className) const
bool removeAnnotations(llvm::function_ref< bool(Annotation)> predicate)
Remove all annotations from this annotation set for which predicate returns true.
Annotation getAnnotationImpl(StringAttr className) const
bool applyToPort(FModuleLike op, size_t portNo) const
Store the annotations in this set in an operation's portAnnotations attribute, overwriting any existi...
ArrayAttr getArrayAttr() const
Return this annotation set as an ArrayAttr.
bool removeAnnotation(Annotation anno)
Remove an annotation from this annotation set.
static AnnotationSet get(Value v)
Get an annotation set for the specified value.
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 hasAnnotation(StringRef className) const
Return true if we have an annotation with the specified class name.
AnnotationSet(MLIRContext *context)
Form an empty annotation set.
static bool removePortAnnotations(Operation *module, llvm::function_ref< bool(unsigned, Annotation)> predicate)
Remove all port annotations from a module or extmodule for which predicate returns true.
static AnnotationSet forPort(FModuleLike op, size_t portNo)
Get an annotation set for the specified port.
bool canBeDeleted() const
Check if every annotation can be deleted.
bool setDontTouch(bool dontTouch)
MLIRContext * getContext() const
Return the MLIRContext corresponding to this AnnotationSet.
This class provides a read-only projection of an annotation.
DictionaryAttr getDict() const
Get the data dictionary of this attribute.
void setDict(DictionaryAttr dict)
Set the data dictionary of this attribute.
unsigned getFieldID() const
Get the field id this attribute targets.
void setMember(StringAttr name, Attribute value)
Add or set a member of the annotation to a value.
bool canBeDeleted()
Returns true if this is an annotation which can be safely deleted without consequence.
void removeMember(StringAttr name)
Remove a member of the annotation.
StringRef getClass() const
Return the 'class' that this annotation is representing.
StringAttr getClassAttr() const
Return the 'class' that this annotation is representing.
bool isClass(Args... names) const
Return true if this annotation matches any of the specified class names.
The target of an inner symbol, the entity the symbol is a handle for.
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
StringRef getAnnotationAttrName()
Return the name of the attribute used for annotations on FIRRTL ops.
LogicalResult extractDUT(FModuleOp mod, FModuleOp &dut)
Utility that searches for a MarkDUTAnnotation on a specific module, mod, and tries to update a design...
constexpr const char * dutAnnoClass
constexpr const char * omirTrackerAnnoClass
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.
bool isOMIRStringEncodedPassthrough(StringRef type)
Check if an OMIR type is a string-encoded value that the FIRRTL dialect simply passes through as a st...
StringRef getPortAnnotationAttrName()
Return the name of the attribute used for port annotations on FIRRTL ops.
ArrayAttr getAnnotationsIfPresent(Operation *op)
constexpr const char * dontTouchAnnoClass
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
An annotation target is used to keep track of something that is targeted by an Annotation.
FIRRTLType getType() const
Get the type of the target.
Attribute getNLAReference(hw::InnerSymbolNamespace &moduleNamespace) const
Get a reference to this target suitable for use in an NLA.
Operation * getOp() const
FModuleLike getModule() const
Get the parent module of the target.
AnnotationSet getAnnotations() const
Get the annotations associated with the target.
void setAnnotations(AnnotationSet annotations) const
Set the annotations associated with the target.
This represents an annotation targeting a specific operation.
Attribute getNLAReference(hw::InnerSymbolNamespace &moduleNamespace) const
void setAnnotations(AnnotationSet annotations) const
FIRRTLType getType() const
AnnotationSet getAnnotations() const
This represents an annotation targeting a specific port of a module, memory, or instance.
FIRRTLType getType() const
AnnotationSet getAnnotations() const
void setAnnotations(AnnotationSet annotations) const
Attribute getNLAReference(hw::InnerSymbolNamespace &moduleNamespace) const
unsigned getPortNo() const
PortAnnoTarget(FModuleLike op, unsigned portNo)