CIRCT 23.0.0git
Loading...
Searching...
No Matches
RTGAttributes.cpp
Go to the documentation of this file.
1//===- RTGAttributes.cpp --------------------------------------------------===//
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
12#include "mlir/IR/Builders.h"
13#include "mlir/IR/DialectImplementation.h"
14#include "llvm/ADT/TypeSwitch.h"
15
16using namespace circt;
17using namespace rtg;
18
19//===----------------------------------------------------------------------===//
20// Helpers
21//===----------------------------------------------------------------------===//
22
23namespace llvm {
24template <typename T>
25// NOLINTNEXTLINE(readability-identifier-naming)
26llvm::hash_code hash_value(const DenseSet<T> &set) {
27 // TODO: improve collision resistance
28 unsigned hash = 0;
29 for (auto element : set)
30 hash ^= element;
31 return hash;
32}
33
34template <typename K, typename V>
35// NOLINTNEXTLINE(readability-identifier-naming)
36llvm::hash_code hash_value(const DenseMap<K, V> &map) {
37 // TODO: improve collision resistance
38 unsigned hash = 0;
39 for (auto [key, value] : map)
40 hash ^= (key ^ value);
41 return hash;
42}
43} // namespace llvm
44
45//===----------------------------------------------------------------------===//
46// SetAttr
47//===----------------------------------------------------------------------===//
48
49LogicalResult
50SetAttr::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
51 rtg::SetType type, const DenseSet<TypedAttr> *elements) {
52
53 // check that all elements have the right type
54 // iterating over the set is fine here because the iteration order is not
55 // visible to the outside (it would not be fine to print the earliest invalid
56 // element)
57 if (!llvm::all_of(*elements, [&](auto element) {
58 return element.getType() == type.getElementType();
59 })) {
60 return emitError() << "all elements must be of the set element type "
61 << type.getElementType();
62 }
63
64 return success();
65}
66
67Attribute SetAttr::parse(AsmParser &odsParser, Type odsType) {
68 DenseSet<TypedAttr> elements;
69 Type elementType;
70 if (odsParser.parseCommaSeparatedList(mlir::AsmParser::Delimiter::LessGreater,
71 [&]() {
72 TypedAttr element;
73 if (odsParser.parseAttribute(element))
74 return failure();
75 elements.insert(element);
76 elementType = element.getType();
77 return success();
78 }))
79 return {};
80
81 auto setType = llvm::dyn_cast_or_null<SetType>(odsType);
82 if (odsType && !setType) {
83 odsParser.emitError(odsParser.getNameLoc())
84 << "type must be a an '!rtg.set' type";
85 return {};
86 }
87
88 if (!setType && elements.empty()) {
89 odsParser.emitError(odsParser.getNameLoc())
90 << "type must be explicitly provided: cannot infer set element type "
91 "from empty set";
92 return {};
93 }
94
95 if (!setType && !elements.empty())
96 setType = SetType::get(elementType);
97
98 return SetAttr::getChecked(
99 odsParser.getEncodedSourceLoc(odsParser.getNameLoc()),
100 odsParser.getContext(), setType, &elements);
101}
102
103void SetAttr::print(AsmPrinter &odsPrinter) const {
104 odsPrinter << "<";
105 // Sort elements lexicographically by their printed string representation
106 SmallVector<std::string> sortedElements;
107 for (auto element : *getElements()) {
108 std::string &elementStr = sortedElements.emplace_back();
109 llvm::raw_string_ostream elementOS(elementStr);
110 element.print(elementOS);
111 }
112 llvm::sort(sortedElements);
113 llvm::interleaveComma(sortedElements, odsPrinter);
114 odsPrinter << ">";
115}
116
117//===----------------------------------------------------------------------===//
118// MapAttr
119//===----------------------------------------------------------------------===//
120
121LogicalResult
122MapAttr::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
123 rtg::MapType type,
124 const DenseMap<TypedAttr, TypedAttr> *entries) {
125
126 // check that all keys and values have the right type
127 if (!llvm::all_of(*entries, [&](auto entry) {
128 return entry.first.getType() == type.getKeyType() &&
129 entry.second.getType() == type.getValueType();
130 })) {
131 return emitError() << "all keys must be of type " << type.getKeyType()
132 << " and all values must be of type "
133 << type.getValueType();
134 }
135
136 return success();
137}
138
139Attribute MapAttr::parse(AsmParser &odsParser, Type odsType) {
140 DenseMap<TypedAttr, TypedAttr> entries;
141 Type keyType, valueType;
142 if (odsParser.parseCommaSeparatedList(
143 mlir::AsmParser::Delimiter::LessGreater, [&]() {
144 TypedAttr key, value;
145 if (odsParser.parseAttribute(key) || odsParser.parseArrow() ||
146 odsParser.parseAttribute(value))
147 return failure();
148 entries.insert({key, value});
149 keyType = key.getType();
150 valueType = value.getType();
151 return success();
152 }))
153 return {};
154
155 auto mapType = llvm::dyn_cast_or_null<MapType>(odsType);
156 if (odsType && !mapType) {
157 odsParser.emitError(odsParser.getNameLoc())
158 << "type must be an '!rtg.map' type";
159 return {};
160 }
161
162 if (!mapType && entries.empty()) {
163 odsParser.emitError(odsParser.getNameLoc())
164 << "type must be explicitly provided: cannot infer map key and value "
165 "types from empty map";
166 return {};
167 }
168
169 if (!mapType && !entries.empty())
170 mapType = MapType::get(keyType, valueType);
171
172 return MapAttr::getChecked(
173 odsParser.getEncodedSourceLoc(odsParser.getNameLoc()),
174 odsParser.getContext(), mapType, &entries);
175}
176
177void MapAttr::print(AsmPrinter &odsPrinter) const {
178 odsPrinter << "<";
179 // Sort entries lexicographically by their printed string representation
180 SmallVector<std::pair<std::string, std::string>> sortedEntries;
181 for (auto [key, value] : *getEntries()) {
182 std::string keyStr, valueStr;
183 llvm::raw_string_ostream keyOS(keyStr);
184 llvm::raw_string_ostream valueOS(valueStr);
185 key.print(keyOS);
186 value.print(valueOS);
187 sortedEntries.emplace_back(std::move(keyStr), std::move(valueStr));
188 }
189 llvm::sort(sortedEntries);
190 llvm::interleaveComma(sortedEntries, odsPrinter, [&](auto &entry) {
191 odsPrinter << entry.first << " -> " << entry.second;
192 });
193 odsPrinter << ">";
194}
195
196//===----------------------------------------------------------------------===//
197// TupleAttr
198//===----------------------------------------------------------------------===//
199
200Type TupleAttr::getType() const {
201 SmallVector<Type> elementTypes(llvm::map_range(
202 getElements(), [](auto element) { return element.getType(); }));
203 return TupleType::get(getContext(), elementTypes);
204}
205
206//===----------------------------------------------------------------------===//
207// VirtualRegisterConfigAttr
208//===----------------------------------------------------------------------===//
209
210Type VirtualRegisterConfigAttr::getType() const {
211 return getAllowedRegs()[0].getType();
212}
213
214LogicalResult VirtualRegisterConfigAttr::verify(
215 llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
216 ArrayRef<rtg::RegisterAttrInterface> allowedRegs) {
217 if (allowedRegs.empty())
218 return emitError() << "must have at least one allowed register";
219
220 if (!llvm::all_of(allowedRegs, [&](auto reg) {
221 return reg.getType() == allowedRegs[0].getType();
222 })) {
223 return emitError() << "all allowed registers must be of the same type";
224 }
225
226 return success();
227}
228
229//===----------------------------------------------------------------------===//
230// LabelAttr
231//===----------------------------------------------------------------------===//
232
233Type LabelAttr::getType() const { return LabelType::get(getContext()); }
234
235//===----------------------------------------------------------------------===//
236// TableGen generated logic.
237//===----------------------------------------------------------------------===//
238
239void RTGDialect::registerAttributes() {
240 addAttributes<
241#define GET_ATTRDEF_LIST
242#include "circt/Dialect/RTG/IR/RTGAttributes.cpp.inc"
243 >();
244}
245
246#define GET_ATTRDEF_CLASSES
247#include "circt/Dialect/RTG/IR/RTGAttributes.cpp.inc"
MlirType elementType
Definition CHIRRTL.cpp:29
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
llvm::hash_code hash_value(const DenseSet< T > &set)
Definition rtg.py:1
reg(value, clock, reset=None, reset_value=None, name=None, sym_name=None)
Definition seq.py:21