CIRCT  20.0.0git
FIRRTLAnnotations.cpp
Go to the documentation of this file.
1 //===- FIRRTLAnnotations.cpp - Code for working with Annotations ----------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements helpers for working with FIRRTL annotations.
10 //
11 //===----------------------------------------------------------------------===//
12 
21 #include "mlir/IR/Operation.h"
22 #include "mlir/Interfaces/FunctionImplementation.h"
23 #include "llvm/ADT/TypeSwitch.h"
24 
25 using namespace circt;
26 using namespace firrtl;
27 
28 static ArrayAttr getAnnotationsFrom(Operation *op) {
29  if (auto annots = getAnnotationsIfPresent(op))
30  return annots;
31  return ArrayAttr::get(op->getContext(), {});
32 }
33 
34 static ArrayAttr getAnnotationsFrom(ArrayRef<Annotation> annotations,
35  MLIRContext *context) {
36  if (annotations.empty())
37  return ArrayAttr::get(context, {});
38  SmallVector<Attribute> attrs;
39  attrs.reserve(annotations.size());
40  for (auto anno : annotations)
41  attrs.push_back(anno.getAttr());
42  return ArrayAttr::get(context, attrs);
43 }
44 
45 /// Form an annotation set from an array of annotation attributes.
46 AnnotationSet::AnnotationSet(ArrayRef<Attribute> annotations,
47  MLIRContext *context)
48  : annotations(ArrayAttr::get(context, annotations)) {}
49 
50 /// Form an annotation set from an array of annotations.
51 AnnotationSet::AnnotationSet(ArrayRef<Annotation> annotations,
52  MLIRContext *context)
53  : annotations(getAnnotationsFrom(annotations, context)) {}
54 
55 /// Form an annotation set with a possibly-null ArrayAttr.
56 AnnotationSet::AnnotationSet(ArrayAttr annotations, MLIRContext *context)
57  : AnnotationSet(annotations ? annotations : ArrayAttr::get(context, {})) {}
58 
59 /// Get an annotation set for the specified operation.
62 
63 static AnnotationSet forPort(Operation *op, size_t portNo) {
64  auto ports = op->getAttrOfType<ArrayAttr>(getPortAnnotationAttrName());
65  if (ports && !ports.empty())
66  return AnnotationSet(cast<ArrayAttr>(ports[portNo]));
67  return AnnotationSet(ArrayAttr::get(op->getContext(), {}));
68 }
69 
70 AnnotationSet AnnotationSet::forPort(FModuleLike op, size_t portNo) {
71  return ::forPort(op.getOperation(), portNo);
72 }
73 
74 AnnotationSet AnnotationSet::forPort(MemOp op, size_t portNo) {
75  return ::forPort(op.getOperation(), portNo);
76 }
77 
78 /// Get an annotation set for the specified value.
80  if (auto *op = v.getDefiningOp())
81  return AnnotationSet(op);
82  // If its not an Operation, then must be a block argument.
83  auto arg = dyn_cast<BlockArgument>(v);
84  auto module = cast<FModuleOp>(arg.getOwner()->getParentOp());
85  return forPort(module, arg.getArgNumber());
86 }
87 
88 /// Store the annotations in this set in an operation's `annotations` attribute,
89 /// overwriting any existing annotations.
90 bool AnnotationSet::applyToOperation(Operation *op) const {
91  auto before = op->getAttrDictionary();
92  op->setAttr(getAnnotationAttrName(), getArrayAttr());
93  return op->getAttrDictionary() != before;
94 }
95 
96 static bool applyToPort(AnnotationSet annos, Operation *op, size_t portCount,
97  size_t portNo) {
98  assert(portNo < portCount && "port index out of range.");
99  auto *context = op->getContext();
100  auto before = op->getAttrOfType<ArrayAttr>(getPortAnnotationAttrName());
101  SmallVector<Attribute> portAnnotations;
102  if (!before || before.empty())
103  portAnnotations.assign(portCount, ArrayAttr::get(context, {}));
104  else
105  portAnnotations.append(before.begin(), before.end());
106  portAnnotations[portNo] = annos.getArrayAttr();
107  auto after = ArrayAttr::get(context, portAnnotations);
108  if (before != after)
109  op->setAttr(getPortAnnotationAttrName(), after);
110  return before != after;
111 }
112 
113 bool AnnotationSet::applyToPort(FModuleLike op, size_t portNo) const {
114  return ::applyToPort(*this, op.getOperation(), op.getNumPorts(), portNo);
115 }
116 
117 bool AnnotationSet::applyToPort(MemOp op, size_t portNo) const {
118  return ::applyToPort(*this, op.getOperation(), op->getNumResults(), portNo);
119 }
120 
121 Annotation AnnotationSet::getAnnotationImpl(StringAttr className) const {
122  for (auto annotation : *this) {
123  if (annotation.getClassAttr() == className)
124  return annotation;
125  }
126  return {};
127 }
128 
129 Annotation AnnotationSet::getAnnotationImpl(StringRef className) const {
130  for (auto annotation : *this) {
131  if (annotation.getClass() == className)
132  return annotation;
133  }
134  return {};
135 }
136 
137 bool AnnotationSet::hasAnnotationImpl(StringAttr className) const {
138  return getAnnotationImpl(className) != Annotation();
139 }
140 
141 bool AnnotationSet::hasAnnotationImpl(StringRef className) const {
142  return getAnnotationImpl(className) != Annotation();
143 }
144 
147 }
148 
149 bool AnnotationSet::setDontTouch(bool dontTouch) {
150  if (dontTouch)
151  return addDontTouch();
152  return removeDontTouch();
153 }
154 
156  if (hasDontTouch())
157  return false;
159  getContext(), {{StringAttr::get(getContext(), "class"),
161  return true;
162 }
163 
166 }
167 
168 bool AnnotationSet::hasDontTouch(Operation *op) {
169  return AnnotationSet(op).hasDontTouch();
170 }
171 
172 bool AnnotationSet::setDontTouch(Operation *op, bool dontTouch) {
173  if (dontTouch)
174  return addDontTouch(op);
175  return removeDontTouch(op);
176 }
177 
178 bool AnnotationSet::addDontTouch(Operation *op) {
179  AnnotationSet annos(op);
180  auto changed = annos.addDontTouch();
181  if (changed)
182  annos.applyToOperation(op);
183  return changed;
184 }
185 
186 bool AnnotationSet::removeDontTouch(Operation *op) {
187  AnnotationSet annos(op);
188  auto changed = annos.removeDontTouch();
189  if (changed)
190  annos.applyToOperation(op);
191  return changed;
192 }
193 
195  return llvm::all_of(annotations, [](Attribute attr) {
196  return Annotation(attr).canBeDeleted();
197  });
198 }
199 
200 bool AnnotationSet::canBeDeleted(Operation *op) {
201  return AnnotationSet(op).canBeDeleted();
202 }
203 
204 /// Add more annotations to this AttributeSet.
205 void AnnotationSet::addAnnotations(ArrayRef<Annotation> newAnnotations) {
206  if (newAnnotations.empty())
207  return;
208 
209  SmallVector<Attribute> annotationVec;
210  annotationVec.reserve(annotations.size() + newAnnotations.size());
211  annotationVec.append(annotations.begin(), annotations.end());
212  for (auto anno : newAnnotations)
213  annotationVec.push_back(anno.getDict());
214  annotations = ArrayAttr::get(getContext(), annotationVec);
215 }
216 
217 void AnnotationSet::addAnnotations(ArrayRef<Attribute> newAnnotations) {
218  if (newAnnotations.empty())
219  return;
220 
221  if (empty()) {
222  annotations = ArrayAttr::get(getContext(), newAnnotations);
223  return;
224  }
225 
226  SmallVector<Attribute> annotationVec;
227  annotationVec.reserve(annotations.size() + newAnnotations.size());
228  annotationVec.append(annotations.begin(), annotations.end());
229  annotationVec.append(newAnnotations.begin(), newAnnotations.end());
230  annotations = ArrayAttr::get(getContext(), annotationVec);
231 }
232 
233 void AnnotationSet::addAnnotations(ArrayAttr newAnnotations) {
234  if (!newAnnotations)
235  return;
236 
237  if (empty()) {
238  annotations = newAnnotations;
239  return;
240  }
241 
242  SmallVector<Attribute> annotationVec;
243  annotationVec.reserve(annotations.size() + newAnnotations.size());
244  annotationVec.append(annotations.begin(), annotations.end());
245  annotationVec.append(newAnnotations.begin(), newAnnotations.end());
246  annotations = ArrayAttr::get(getContext(), annotationVec);
247 }
248 
249 /// Remove an annotation from this annotation set. Returns true if any were
250 /// removed, false otherwise.
252  return removeAnnotations([&](Annotation other) { return other == anno; });
253 }
254 
255 /// Remove an annotation from this annotation set. Returns true if any were
256 /// removed, false otherwise.
257 bool AnnotationSet::removeAnnotation(Attribute anno) {
258  return removeAnnotations(
259  [&](Annotation other) { return other.getDict() == anno; });
260 }
261 
262 /// Remove an annotation from this annotation set. Returns true if any were
263 /// removed, false otherwise.
264 bool AnnotationSet::removeAnnotation(StringRef className) {
265  return removeAnnotations(
266  [&](Annotation other) { return other.getClass() == className; });
267 }
268 
269 /// Remove all annotations from this annotation set for which `predicate`
270 /// returns true.
272  llvm::function_ref<bool(Annotation)> predicate) {
273  // Search for the first match.
274  ArrayRef<Attribute> annos = getArrayAttr().getValue();
275  auto *it = annos.begin();
276  while (it != annos.end() && !predicate(Annotation(*it)))
277  ++it;
278 
279  // Fast path for sets where the predicate never matched.
280  if (it == annos.end())
281  return false;
282 
283  // Build a filtered list of annotations.
284  SmallVector<Attribute> filteredAnnos;
285  filteredAnnos.reserve(annos.size());
286  filteredAnnos.append(annos.begin(), it);
287  ++it;
288  while (it != annos.end()) {
289  if (!predicate(Annotation(*it)))
290  filteredAnnos.push_back(*it);
291  ++it;
292  }
293  annotations = ArrayAttr::get(getContext(), filteredAnnos);
294  return true;
295 }
296 
297 /// Remove all annotations from an operation for which `predicate` returns true.
299  Operation *op, llvm::function_ref<bool(Annotation)> predicate) {
300  // Fast-path for no annotations.
301  auto annosArray = getAnnotationsIfPresent(op);
302  if (!annosArray)
303  return false;
304  AnnotationSet annos(annosArray);
305  if (annos.removeAnnotations(predicate)) {
306  annos.applyToOperation(op);
307  return true;
308  }
309  return false;
310 }
311 
312 bool AnnotationSet::removeAnnotations(Operation *op, StringRef className) {
313  return removeAnnotations(
314  op, [&](Annotation a) { return (a.getClass() == className); });
315 }
316 
317 /// Remove all port annotations from a module or extmodule for which `predicate`
318 /// returns true.
320  Operation *module,
321  llvm::function_ref<bool(unsigned, Annotation)> predicate) {
322  auto ports = dyn_cast_or_null<ArrayAttr>(module->getAttr("portAnnotations"));
323  if (!ports || ports.empty())
324  return false;
325 
326  // Collect results
327  SmallVector<Attribute> newAnnos;
328 
329  // Filter the annotations on each argument.
330  bool changed = false;
331  for (unsigned argNum = 0, argNumEnd = ports.size(); argNum < argNumEnd;
332  ++argNum) {
333  AnnotationSet annos(AnnotationSet(cast<ArrayAttr>(ports[argNum])));
334 
335  // Go through all annotations on this port and extract the interesting
336  // ones. If any modifications were done, keep a reduced set of attributes
337  // around for the port, otherwise just stick with the existing ones.
338  if (!annos.empty())
339  changed |= annos.removeAnnotations(
340  [&](Annotation anno) { return predicate(argNum, anno); });
341  newAnnos.push_back(annos.getArrayAttr());
342  }
343 
344  // If we have made any changes, apply them to the operation.
345  if (changed)
346  module->setAttr("portAnnotations",
347  ArrayAttr::get(module->getContext(), newAnnos));
348  return changed;
349 }
350 
351 //===----------------------------------------------------------------------===//
352 // Annotation
353 //===----------------------------------------------------------------------===//
354 
355 DictionaryAttr Annotation::getDict() const {
356  return cast<DictionaryAttr>(attr);
357 }
358 
359 void Annotation::setDict(DictionaryAttr dict) { attr = dict; }
360 
361 unsigned Annotation::getFieldID() const {
362  if (auto fieldID = getMember<IntegerAttr>("circt.fieldID"))
363  return fieldID.getInt();
364  return 0;
365 }
366 
367 /// Return the 'class' that this annotation is representing.
368 StringAttr Annotation::getClassAttr() const {
369  return getDict().getAs<StringAttr>("class");
370 }
371 
372 /// Return the 'class' that this annotation is representing.
373 StringRef Annotation::getClass() const {
374  if (auto classAttr = getClassAttr())
375  return classAttr.getValue();
376  return {};
377 }
378 
379 void Annotation::setMember(StringAttr name, Attribute value) {
380  setMember(name.getValue(), value);
381 }
382 
383 void Annotation::setMember(StringRef name, Attribute value) {
384  // Binary search for the matching field.
385  auto dict = getDict();
386  auto [it, found] = mlir::impl::findAttrSorted(dict.begin(), dict.end(), name);
387  auto index = std::distance(dict.begin(), it);
388  // Create an array for the new members.
389  SmallVector<NamedAttribute> attributes;
390  attributes.reserve(dict.size() + 1);
391  // Copy over the leading annotations.
392  for (auto field : dict.getValue().take_front(index))
393  attributes.push_back(field);
394  // Push the new member.
395  auto nameAttr = StringAttr::get(dict.getContext(), name);
396  attributes.push_back(NamedAttribute(nameAttr, value));
397  // Copy remaining members, skipping the old field value.
398  for (auto field : dict.getValue().drop_front(index + found))
399  attributes.push_back(field);
400  // Commit the dictionary.
401  setDict(DictionaryAttr::getWithSorted(dict.getContext(), attributes));
402 }
403 
404 void Annotation::removeMember(StringAttr name) {
405  auto dict = getDict();
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++));
412  // If the member was not here, just return.
413  if (i == e)
414  return;
415  // Copy the rest of the members over.
416  attributes.append(++i, e);
417  // Commit the dictionary.
418  setDict(DictionaryAttr::getWithSorted(dict.getContext(), attributes));
419 }
420 
421 void Annotation::removeMember(StringRef name) {
422  // Binary search for the matching field.
423  auto dict = getDict();
424  auto [it, found] = mlir::impl::findAttrSorted(dict.begin(), dict.end(), name);
425  auto index = std::distance(dict.begin(), it);
426  if (!found)
427  return;
428  // Create an array for the new members.
429  SmallVector<NamedAttribute> attributes;
430  attributes.reserve(dict.size() - 1);
431  // Copy over the leading annotations.
432  for (auto field : dict.getValue().take_front(index))
433  attributes.push_back(field);
434  // Copy remaining members, skipping the old field value.
435  for (auto field : dict.getValue().drop_front(index + 1))
436  attributes.push_back(field);
437  // Commit the dictionary.
438  setDict(DictionaryAttr::getWithSorted(dict.getContext(), attributes));
439 }
440 
442 
443  // The only annotations which can be deleted are OM-affiliated.
445  return false;
446 
447  auto tpe = getMember<StringAttr>("type");
448  return tpe &&
449  (tpe == "OMReferenceTarget" || tpe == "OMMemberReferenceTarget" ||
450  tpe == "OMMemberInstanceTarget");
451 }
452 
453 void Annotation::dump() { attr.dump(); }
454 
455 //===----------------------------------------------------------------------===//
456 // AnnotationSetIterator
457 //===----------------------------------------------------------------------===//
458 
460  return Annotation(this->getBase().getArray()[this->getIndex()]);
461 }
462 
463 //===----------------------------------------------------------------------===//
464 // AnnoTarget
465 //===----------------------------------------------------------------------===//
466 
467 FModuleLike AnnoTarget::getModule() const {
468  auto *op = getOp();
469  if (auto module = llvm::dyn_cast<FModuleLike>(op))
470  return module;
471  return op->getParentOfType<FModuleLike>();
472 }
473 
475  return TypeSwitch<AnnoTarget, AnnotationSet>(*this)
477  [&](auto target) { return target.getAnnotations(); })
478  .Default([&](auto target) { return AnnotationSet(getOp()); });
479 }
480 
481 void AnnoTarget::setAnnotations(AnnotationSet annotations) const {
482  TypeSwitch<AnnoTarget>(*this).Case<OpAnnoTarget, PortAnnoTarget>(
483  [&](auto target) { target.setAnnotations(annotations); });
484 }
485 
486 Attribute
488  return TypeSwitch<AnnoTarget, Attribute>(*this)
490  [&](auto target) { return target.getNLAReference(moduleNamespace); })
491  .Default([](auto target) { return Attribute(); });
492 }
493 
495  return TypeSwitch<AnnoTarget, FIRRTLType>(*this)
497  [](auto target) { return target.getType(); })
498  .Default([](auto target) { return FIRRTLType(); });
499 }
500 
502  return AnnotationSet(getOp());
503 }
504 
506  annotations.applyToOperation(getOp());
507 }
508 
509 Attribute
511  // If the op is a module, just return the module name.
512  if (auto module = llvm::dyn_cast<FModuleLike>(getOp())) {
513  assert(module.getModuleNameAttr() && "invalid NLA reference");
514  return FlatSymbolRefAttr::get(module.getModuleNameAttr());
515  }
516  // Return an inner-ref to the target.
518  getOp(), [&moduleNamespace](auto _) -> hw::InnerSymbolNamespace & {
519  return moduleNamespace;
520  });
521 }
522 
524  auto *op = getOp();
525  // Annotations that target operations are resolved like inner symbols.
526  if (auto is = llvm::dyn_cast<hw::InnerSymbolOpInterface>(op)) {
527  auto result = is.getTargetResult();
528  if (!result)
529  return {};
530  return type_cast<FIRRTLType>(result.getType());
531  }
532  // Fallback to assuming the single result is the target.
533  if (op->getNumResults() != 1)
534  return {};
535  return type_cast<FIRRTLType>(op->getResult(0).getType());
536 }
537 
538 PortAnnoTarget::PortAnnoTarget(FModuleLike op, unsigned portNo)
539  : AnnoTarget({op, portNo}) {}
540 
541 PortAnnoTarget::PortAnnoTarget(MemOp op, unsigned portNo)
542  : AnnoTarget({op, portNo}) {}
543 
545  if (auto memOp = llvm::dyn_cast<MemOp>(getOp()))
546  return AnnotationSet::forPort(memOp, getPortNo());
547  if (auto moduleOp = llvm::dyn_cast<FModuleLike>(getOp()))
548  return AnnotationSet::forPort(moduleOp, getPortNo());
549  llvm_unreachable("unknown port target");
550  return AnnotationSet(getOp()->getContext());
551 }
552 
554  if (auto memOp = llvm::dyn_cast<MemOp>(getOp()))
555  annotations.applyToPort(memOp, getPortNo());
556  else if (auto moduleOp = llvm::dyn_cast<FModuleLike>(getOp()))
557  annotations.applyToPort(moduleOp, getPortNo());
558  else
559  llvm_unreachable("unknown port target");
560 }
561 
563  hw::InnerSymbolNamespace &moduleNamespace) const {
564  auto module = llvm::dyn_cast<FModuleLike>(getOp());
565  auto target = module ? hw::InnerSymTarget(getPortNo(), module)
568  target, [&moduleNamespace](auto _) -> hw::InnerSymbolNamespace & {
569  return moduleNamespace;
570  });
571 }
572 
574  auto *op = getOp();
575  if (auto module = llvm::dyn_cast<FModuleLike>(op))
576  return type_cast<FIRRTLType>(module.getPortType(getPortNo()));
577  if (llvm::isa<MemOp, InstanceOp>(op))
578  return type_cast<FIRRTLType>(op->getResult(getPortNo()).getType());
579  llvm_unreachable("unknown operation kind");
580  return {};
581 }
582 
583 //===----------------------------------------------------------------------===//
584 // Annotation Details
585 //===----------------------------------------------------------------------===//
586 
587 /// Check if an OMIR type is a string-encoded value that the FIRRTL dialect
588 /// simply passes through as a string without any decoding.
590  return type == "OMID" || type == "OMReference" || type == "OMBigInt" ||
591  type == "OMLong" || type == "OMString" || type == "OMDouble" ||
592  type == "OMBigDecimal" || type == "OMDeleted";
593 }
594 
595 //===----------------------------------------------------------------------===//
596 // Utilities for Specific Annotations
597 //
598 // TODO: Remove these in favor of first-class annotations.
599 //===----------------------------------------------------------------------===//
600 
601 LogicalResult circt::firrtl::extractDUT(const FModuleOp mod, FModuleOp &dut) {
602  if (!AnnotationSet(mod).hasAnnotation(dutAnnoClass))
603  return success();
604 
605  // TODO: This check is duplicated multiple places. This should be factored
606  // out as part of the annotation lowering pass.
607  if (dut) {
608  auto diag = emitError(mod->getLoc())
609  << "is marked with a '" << dutAnnoClass << "', but '"
610  << dut.getModuleName()
611  << "' also had such an annotation (this should "
612  "be impossible!)";
613  diag.attachNote(dut.getLoc()) << "the first DUT was found here";
614  return failure();
615  }
616  dut = mod;
617  return success();
618 }
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)
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.
Definition: CalyxOps.cpp:55
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.
Definition: DebugAnalysis.h:21
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
AnnotationSet getAnnotations() const
This represents an annotation targeting a specific port of a module, memory, or instance.
AnnotationSet getAnnotations() const
void setAnnotations(AnnotationSet annotations) const
Attribute getNLAReference(hw::InnerSymbolNamespace &moduleNamespace) const
PortAnnoTarget(FModuleLike op, unsigned portNo)