CIRCT  20.0.0git
SVAttributes.cpp
Go to the documentation of this file.
1 //===- SVAttributes.cpp - Implement SV attributes -------------------------===//
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 
11 #include "circt/Dialect/SV/SVOps.h"
13 #include "circt/Support/LLVM.h"
14 #include "mlir/IR/DialectImplementation.h"
15 #include "llvm/ADT/SmallPtrSet.h"
16 #include "llvm/ADT/TypeSwitch.h"
17 
18 using namespace circt;
19 using namespace circt::sv;
20 
21 //===----------------------------------------------------------------------===//
22 // ODS Boilerplate
23 //===----------------------------------------------------------------------===//
24 
25 #define GET_ATTRDEF_CLASSES
26 #include "circt/Dialect/SV/SVAttributes.cpp.inc"
27 
28 #include "circt/Dialect/SV/SVEnums.cpp.inc"
29 
30 void SVDialect::registerAttributes() {
31  addAttributes<
32 #define GET_ATTRDEF_LIST
33 #include "circt/Dialect/SV/SVAttributes.cpp.inc"
34  >();
35 }
36 
37 //===----------------------------------------------------------------------===//
38 // SV Attribute Modification Helpers
39 //===----------------------------------------------------------------------===//
40 
41 bool sv::hasSVAttributes(Operation *op) {
42  if (auto attrs = getSVAttributes(op))
43  return !attrs.empty();
44  return false;
45 }
46 
47 ArrayAttr sv::getSVAttributes(Operation *op) {
48  auto attrs = op->getAttr(SVAttributeAttr::getSVAttributesAttrName());
49  if (!attrs)
50  return {};
51  auto arrayAttr = dyn_cast<ArrayAttr>(attrs);
52  if (!arrayAttr) {
53  op->emitOpError("'sv.attributes' must be an array attribute");
54  return {};
55  }
56  for (auto attr : arrayAttr) {
57  if (!isa<SVAttributeAttr>(attr)) {
58  op->emitOpError("'sv.attributes' elements must be `SVAttributeAttr`s");
59  return {};
60  }
61  }
62  if (arrayAttr.empty())
63  return {};
64  return arrayAttr;
65 }
66 
67 void sv::setSVAttributes(Operation *op, ArrayAttr attrs) {
68  if (attrs && !attrs.getValue().empty())
69  op->setAttr(SVAttributeAttr::getSVAttributesAttrName(), attrs);
70  else
71  op->removeAttr(SVAttributeAttr::getSVAttributesAttrName());
72 }
73 
74 void sv::setSVAttributes(Operation *op, ArrayRef<SVAttributeAttr> attrs) {
75  if (attrs.empty())
76  return sv::setSVAttributes(op, ArrayAttr());
77  SmallVector<Attribute> filteredAttrs;
78  SmallPtrSet<Attribute, 4> seenAttrs;
79  filteredAttrs.reserve(attrs.size());
80  for (auto attr : attrs)
81  if (seenAttrs.insert(attr).second)
82  filteredAttrs.push_back(attr);
83  sv::setSVAttributes(op, ArrayAttr::get(op->getContext(), filteredAttrs));
84 }
85 
87  Operation *op, llvm::function_ref<void(SmallVectorImpl<SVAttributeAttr> &)>
88  modifyCallback) {
89  ArrayRef<Attribute> oldAttrs;
90  if (auto attrs = sv::getSVAttributes(op))
91  oldAttrs = attrs.getValue();
92 
93  SmallVector<SVAttributeAttr> newAttrs;
94  newAttrs.reserve(oldAttrs.size());
95  for (auto oldAttr : oldAttrs)
96  newAttrs.push_back(cast<SVAttributeAttr>(oldAttr));
97  modifyCallback(newAttrs);
98 
99  if (newAttrs.size() == oldAttrs.size() &&
100  llvm::none_of(llvm::zip(oldAttrs, newAttrs), [](auto pair) {
101  return std::get<0>(pair) != std::get<1>(pair);
102  }))
103  return false;
104 
105  sv::setSVAttributes(op, newAttrs);
106  return true;
107 }
108 
109 unsigned sv::addSVAttributes(Operation *op,
110  ArrayRef<SVAttributeAttr> newAttrs) {
111  if (newAttrs.empty())
112  return 0;
113  unsigned numAdded = 0;
114  modifySVAttributes(op, [&](auto &attrs) {
115  SmallPtrSet<Attribute, 4> seenAttrs(attrs.begin(), attrs.end());
116  for (auto newAttr : newAttrs) {
117  if (seenAttrs.insert(newAttr).second) {
118  attrs.push_back(newAttr);
119  ++numAdded;
120  }
121  }
122  });
123  return numAdded;
124 }
125 
126 unsigned sv::removeSVAttributes(
127  Operation *op, llvm::function_ref<bool(SVAttributeAttr)> removeCallback) {
128  unsigned numRemoved = 0;
129  sv::modifySVAttributes(op, [&](auto &attrs) {
130  // Only keep attributes for which the callback returns false.
131  unsigned inIdx = 0, outIdx = 0, endIdx = attrs.size();
132  for (; inIdx != endIdx; ++inIdx) {
133  if (removeCallback(attrs[inIdx]))
134  ++numRemoved;
135  else
136  attrs[outIdx++] = attrs[inIdx];
137  }
138  attrs.truncate(outIdx);
139  });
140  return numRemoved;
141 }
142 
143 unsigned sv::removeSVAttributes(Operation *op,
144  ArrayRef<SVAttributeAttr> attrs) {
145  SmallPtrSet<Attribute, 4> attrSet;
146  for (auto attr : attrs)
147  attrSet.insert(attr);
148  return removeSVAttributes(op,
149  [&](auto attr) { return attrSet.contains(attr); });
150 }
151 
152 //===----------------------------------------------------------------------===//
153 // SVAttributeAttr
154 //===----------------------------------------------------------------------===//
155 
156 mlir::Attribute SVAttributeAttr::parse(mlir::AsmParser &p, mlir::Type type) {
157  StringAttr nameAttr;
158  if (p.parseLess() || p.parseAttribute(nameAttr))
159  return {};
160 
161  StringAttr expressionAttr;
162  if (!p.parseOptionalEqual())
163  if (p.parseAttribute(expressionAttr))
164  return {};
165 
166  bool emitAsComment = false;
167  if (!p.parseOptionalComma()) {
168  if (p.parseKeyword("emitAsComment"))
169  return {};
170  emitAsComment = true;
171  }
172 
173  if (p.parseGreater())
174  return {};
175 
176  return SVAttributeAttr::get(p.getContext(), nameAttr, expressionAttr,
177  BoolAttr::get(p.getContext(), emitAsComment));
178 }
179 
180 void SVAttributeAttr::print(::mlir::AsmPrinter &p) const {
181  p << "<" << getName();
182  if (auto expr = getExpression())
183  p << " = " << expr;
184  if (getEmitAsComment().getValue())
185  p << ", emitAsComment";
186  p << ">";
187 }
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition: CalyxOps.cpp:55
StringAttr getName(ArrayAttr names, size_t idx)
Return the name at the specified index of the ArrayAttr or null if it cannot be determined.
mlir::ArrayAttr getSVAttributes(mlir::Operation *op)
Return all the SV attributes of an operation, or null if there are none.
unsigned removeSVAttributes(mlir::Operation *op, llvm::function_ref< bool(SVAttributeAttr)> removeCallback)
Remove the SV attributes from an operation for which removeCallback returns true.
bool modifySVAttributes(mlir::Operation *op, llvm::function_ref< void(llvm::SmallVectorImpl< SVAttributeAttr > &)> modifyCallback)
Modify the list of SV attributes of an operation.
bool hasSVAttributes(mlir::Operation *op)
Helper functions to handle SV attributes.
unsigned addSVAttributes(mlir::Operation *op, llvm::ArrayRef< SVAttributeAttr > attrs)
Add a list of SV attributes to an operation.
void setSVAttributes(mlir::Operation *op, mlir::ArrayAttr attrs)
Set the SV attributes of an operation.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21