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)
196 if (newAnnotations.empty())
199 SmallVector<Attribute> annotationVec;
200 annotationVec.reserve(
annotations.size() + newAnnotations.size());
202 for (
auto anno : newAnnotations)
203 annotationVec.push_back(anno.getDict());
208 if (newAnnotations.empty())
216 SmallVector<Attribute> annotationVec;
217 annotationVec.reserve(
annotations.size() + newAnnotations.size());
219 annotationVec.append(newAnnotations.begin(), newAnnotations.end());
232 SmallVector<Attribute> annotationVec;
233 annotationVec.reserve(
annotations.size() + newAnnotations.size());
235 annotationVec.append(newAnnotations.begin(), newAnnotations.end());
262 llvm::function_ref<
bool(
Annotation)> predicate) {
265 auto *it = annos.begin();
266 while (it != annos.end() && !predicate(
Annotation(*it)))
270 if (it == annos.end())
274 SmallVector<Attribute> filteredAnnos;
275 filteredAnnos.reserve(annos.size());
276 filteredAnnos.append(annos.begin(), it);
278 while (it != annos.end()) {
280 filteredAnnos.push_back(*it);
289 Operation *op, llvm::function_ref<
bool(
Annotation)> predicate) {
311 llvm::function_ref<
bool(
unsigned,
Annotation)> predicate) {
312 auto ports = dyn_cast_or_null<ArrayAttr>(module->getAttr(
"portAnnotations"));
313 if (!ports || ports.empty())
317 SmallVector<Attribute> newAnnos;
320 bool changed =
false;
321 for (
unsigned argNum = 0, argNumEnd = ports.size(); argNum < argNumEnd;
330 [&](
Annotation anno) {
return predicate(argNum, anno); });
336 module->setAttr(
"portAnnotations",
346 return cast<DictionaryAttr>(
attr);
352 if (
auto fieldID = getMember<IntegerAttr>(
"circt.fieldID"))
353 return fieldID.getInt();
359 return getDict().getAs<StringAttr>(
"class");
365 return classAttr.getValue();
376 auto [it, found] = mlir::impl::findAttrSorted(dict.begin(), dict.end(), name);
377 auto index = std::distance(dict.begin(), it);
379 SmallVector<NamedAttribute> attributes;
380 attributes.reserve(dict.size() + 1);
382 for (
auto field : dict.getValue().take_front(index))
383 attributes.push_back(field);
386 attributes.push_back(NamedAttribute(nameAttr, value));
388 for (
auto field : dict.getValue().drop_front(index + found))
389 attributes.push_back(field);
391 setDict(DictionaryAttr::getWithSorted(dict.getContext(), attributes));
396 SmallVector<NamedAttribute> attributes;
397 attributes.reserve(dict.size() - 1);
398 auto *i = dict.begin();
399 auto *e = dict.end();
400 while (i != e && i->getValue() != name)
401 attributes.push_back(*(i++));
406 attributes.append(++i, e);
408 setDict(DictionaryAttr::getWithSorted(dict.getContext(), attributes));
414 auto [it, found] = mlir::impl::findAttrSorted(dict.begin(), dict.end(), name);
415 auto index = std::distance(dict.begin(), it);
419 SmallVector<NamedAttribute> attributes;
420 attributes.reserve(dict.size() - 1);
422 for (
auto field : dict.getValue().take_front(index))
423 attributes.push_back(field);
425 for (
auto field : dict.getValue().drop_front(index + 1))
426 attributes.push_back(field);
428 setDict(DictionaryAttr::getWithSorted(dict.getContext(), attributes));
438 return Annotation(this->getBase().getArray()[this->getIndex()]);
447 if (
auto module = llvm::dyn_cast<FModuleLike>(op))
449 return op->getParentOfType<FModuleLike>();
453 return TypeSwitch<AnnoTarget, AnnotationSet>(*
this)
455 [&](
auto target) {
return target.getAnnotations(); })
461 [&](
auto target) { target.setAnnotations(annotations); });
466 return TypeSwitch<AnnoTarget, Attribute>(*
this)
468 [&](
auto target) {
return target.getNLAReference(moduleNamespace); })
469 .Default([](
auto target) {
return Attribute(); });
473 return TypeSwitch<AnnoTarget, FIRRTLType>(*
this)
475 [](
auto target) {
return target.getType(); })
476 .Default([](
auto target) {
return FIRRTLType(); });
490 if (
auto module = llvm::dyn_cast<FModuleLike>(
getOp())) {
491 assert(module.getModuleNameAttr() &&
"invalid NLA reference");
497 return moduleNamespace;
504 if (
auto is = llvm::dyn_cast<hw::InnerSymbolOpInterface>(op)) {
505 auto result = is.getTargetResult();
508 return type_cast<FIRRTLType>(result.getType());
511 if (op->getNumResults() != 1)
513 return type_cast<FIRRTLType>(op->getResult(0).getType());
523 if (
auto memOp = llvm::dyn_cast<MemOp>(
getOp()))
525 if (
auto moduleOp = llvm::dyn_cast<FModuleLike>(
getOp()))
527 llvm_unreachable(
"unknown port target");
532 if (
auto memOp = llvm::dyn_cast<MemOp>(
getOp()))
534 else if (
auto moduleOp = llvm::dyn_cast<FModuleLike>(
getOp()))
537 llvm_unreachable(
"unknown port target");
542 auto module = llvm::dyn_cast<FModuleLike>(
getOp());
547 return moduleNamespace;
553 if (
auto module = llvm::dyn_cast<FModuleLike>(op))
554 return type_cast<FIRRTLType>(module.getPortType(
getPortNo()));
555 if (llvm::isa<MemOp, InstanceOp>(op))
557 llvm_unreachable(
"unknown operation kind");
575 auto diag = emitError(mod->getLoc())
577 << dut.getModuleName()
578 <<
"' also had such an annotation (this should "
580 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 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.
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.
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.
constexpr const char * dutAnnoClass
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.
LogicalResult extractDUT(FModuleLike mod, FModuleLike &dut)
Utility that searches for a MarkDUTAnnotation on a specific module, mod, and tries to update a design...
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)