CIRCT 20.0.0git
Loading...
Searching...
No Matches
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
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
18using namespace circt;
19using 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
30void 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
41bool sv::hasSVAttributes(Operation *op) {
42 if (auto attrs = getSVAttributes(op))
43 return !attrs.empty();
44 return false;
45}
46
47ArrayAttr 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
67void 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
74void 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
86bool sv::modifySVAttributes(
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
109unsigned 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
126unsigned 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
143unsigned 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
156mlir::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
180void 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}
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.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.